bash-classify 0.1.0__tar.gz → 0.1.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (170) hide show
  1. bash_classify-0.1.2/.claude-plugin/marketplace.json +21 -0
  2. {bash_classify-0.1.0 → bash_classify-0.1.2}/PKG-INFO +40 -28
  3. {bash_classify-0.1.0 → bash_classify-0.1.2}/README.md +39 -27
  4. {bash_classify-0.1.0 → bash_classify-0.1.2}/coding-agent-plugins/claude-code/.claude-plugin/plugin.json +1 -1
  5. {bash_classify-0.1.0 → bash_classify-0.1.2}/coding-agent-plugins/claude-code/hooks/classify-bash.sh +1 -1
  6. {bash_classify-0.1.0 → bash_classify-0.1.2}/src/bash_classify/cli.py +26 -0
  7. bash_classify-0.1.0/.claude-plugin/marketplace.json +0 -13
  8. {bash_classify-0.1.0 → bash_classify-0.1.2}/.claude/rules/command-database.md +0 -0
  9. {bash_classify-0.1.0 → bash_classify-0.1.2}/.editorconfig +0 -0
  10. {bash_classify-0.1.0 → bash_classify-0.1.2}/.github/workflows/ci.yml +0 -0
  11. {bash_classify-0.1.0 → bash_classify-0.1.2}/.github/workflows/publish.yml +0 -0
  12. {bash_classify-0.1.0 → bash_classify-0.1.2}/.gitignore +0 -0
  13. {bash_classify-0.1.0 → bash_classify-0.1.2}/.python-version +0 -0
  14. {bash_classify-0.1.0 → bash_classify-0.1.2}/CLAUDE.md +0 -0
  15. {bash_classify-0.1.0 → bash_classify-0.1.2}/LICENSE +0 -0
  16. {bash_classify-0.1.0 → bash_classify-0.1.2}/SPEC.md +0 -0
  17. {bash_classify-0.1.0 → bash_classify-0.1.2}/coding-agent-plugins/claude-code/hooks/hooks.json +0 -0
  18. {bash_classify-0.1.0 → bash_classify-0.1.2}/docs/classification-guidance.md +0 -0
  19. {bash_classify-0.1.0 → bash_classify-0.1.2}/pyproject.toml +0 -0
  20. {bash_classify-0.1.0 → bash_classify-0.1.2}/ruff.toml +0 -0
  21. {bash_classify-0.1.0 → bash_classify-0.1.2}/schemas/command.schema.json +0 -0
  22. {bash_classify-0.1.0 → bash_classify-0.1.2}/src/bash_classify/__init__.py +0 -0
  23. {bash_classify-0.1.0 → bash_classify-0.1.2}/src/bash_classify/__main__.py +0 -0
  24. {bash_classify-0.1.0 → bash_classify-0.1.2}/src/bash_classify/classifier.py +0 -0
  25. {bash_classify-0.1.0 → bash_classify-0.1.2}/src/bash_classify/commands/apt.yaml +0 -0
  26. {bash_classify-0.1.0 → bash_classify-0.1.2}/src/bash_classify/commands/awk.yaml +0 -0
  27. {bash_classify-0.1.0 → bash_classify-0.1.2}/src/bash_classify/commands/basename.yaml +0 -0
  28. {bash_classify-0.1.0 → bash_classify-0.1.2}/src/bash_classify/commands/bash.yaml +0 -0
  29. {bash_classify-0.1.0 → bash_classify-0.1.2}/src/bash_classify/commands/brew.yaml +0 -0
  30. {bash_classify-0.1.0 → bash_classify-0.1.2}/src/bash_classify/commands/builtin.yaml +0 -0
  31. {bash_classify-0.1.0 → bash_classify-0.1.2}/src/bash_classify/commands/cargo.yaml +0 -0
  32. {bash_classify-0.1.0 → bash_classify-0.1.2}/src/bash_classify/commands/cat.yaml +0 -0
  33. {bash_classify-0.1.0 → bash_classify-0.1.2}/src/bash_classify/commands/chgrp.yaml +0 -0
  34. {bash_classify-0.1.0 → bash_classify-0.1.2}/src/bash_classify/commands/chmod.yaml +0 -0
  35. {bash_classify-0.1.0 → bash_classify-0.1.2}/src/bash_classify/commands/chown.yaml +0 -0
  36. {bash_classify-0.1.0 → bash_classify-0.1.2}/src/bash_classify/commands/column.yaml +0 -0
  37. {bash_classify-0.1.0 → bash_classify-0.1.2}/src/bash_classify/commands/comm.yaml +0 -0
  38. {bash_classify-0.1.0 → bash_classify-0.1.2}/src/bash_classify/commands/command.yaml +0 -0
  39. {bash_classify-0.1.0 → bash_classify-0.1.2}/src/bash_classify/commands/cp.yaml +0 -0
  40. {bash_classify-0.1.0 → bash_classify-0.1.2}/src/bash_classify/commands/curl.yaml +0 -0
  41. {bash_classify-0.1.0 → bash_classify-0.1.2}/src/bash_classify/commands/cut.yaml +0 -0
  42. {bash_classify-0.1.0 → bash_classify-0.1.2}/src/bash_classify/commands/date.yaml +0 -0
  43. {bash_classify-0.1.0 → bash_classify-0.1.2}/src/bash_classify/commands/df.yaml +0 -0
  44. {bash_classify-0.1.0 → bash_classify-0.1.2}/src/bash_classify/commands/diff.yaml +0 -0
  45. {bash_classify-0.1.0 → bash_classify-0.1.2}/src/bash_classify/commands/dig.yaml +0 -0
  46. {bash_classify-0.1.0 → bash_classify-0.1.2}/src/bash_classify/commands/dirname.yaml +0 -0
  47. {bash_classify-0.1.0 → bash_classify-0.1.2}/src/bash_classify/commands/docker.yaml +0 -0
  48. {bash_classify-0.1.0 → bash_classify-0.1.2}/src/bash_classify/commands/du.yaml +0 -0
  49. {bash_classify-0.1.0 → bash_classify-0.1.2}/src/bash_classify/commands/echo.yaml +0 -0
  50. {bash_classify-0.1.0 → bash_classify-0.1.2}/src/bash_classify/commands/env.yaml +0 -0
  51. {bash_classify-0.1.0 → bash_classify-0.1.2}/src/bash_classify/commands/expand.yaml +0 -0
  52. {bash_classify-0.1.0 → bash_classify-0.1.2}/src/bash_classify/commands/false.yaml +0 -0
  53. {bash_classify-0.1.0 → bash_classify-0.1.2}/src/bash_classify/commands/file.yaml +0 -0
  54. {bash_classify-0.1.0 → bash_classify-0.1.2}/src/bash_classify/commands/find.yaml +0 -0
  55. {bash_classify-0.1.0 → bash_classify-0.1.2}/src/bash_classify/commands/fmt.yaml +0 -0
  56. {bash_classify-0.1.0 → bash_classify-0.1.2}/src/bash_classify/commands/fold.yaml +0 -0
  57. {bash_classify-0.1.0 → bash_classify-0.1.2}/src/bash_classify/commands/free.yaml +0 -0
  58. {bash_classify-0.1.0 → bash_classify-0.1.2}/src/bash_classify/commands/gawk.yaml +0 -0
  59. {bash_classify-0.1.0 → bash_classify-0.1.2}/src/bash_classify/commands/git.yaml +0 -0
  60. {bash_classify-0.1.0 → bash_classify-0.1.2}/src/bash_classify/commands/go.yaml +0 -0
  61. {bash_classify-0.1.0 → bash_classify-0.1.2}/src/bash_classify/commands/grep.yaml +0 -0
  62. {bash_classify-0.1.0 → bash_classify-0.1.2}/src/bash_classify/commands/groups.yaml +0 -0
  63. {bash_classify-0.1.0 → bash_classify-0.1.2}/src/bash_classify/commands/gunzip.yaml +0 -0
  64. {bash_classify-0.1.0 → bash_classify-0.1.2}/src/bash_classify/commands/gzip.yaml +0 -0
  65. {bash_classify-0.1.0 → bash_classify-0.1.2}/src/bash_classify/commands/head.yaml +0 -0
  66. {bash_classify-0.1.0 → bash_classify-0.1.2}/src/bash_classify/commands/helm.yaml +0 -0
  67. {bash_classify-0.1.0 → bash_classify-0.1.2}/src/bash_classify/commands/hostname.yaml +0 -0
  68. {bash_classify-0.1.0 → bash_classify-0.1.2}/src/bash_classify/commands/id.yaml +0 -0
  69. {bash_classify-0.1.0 → bash_classify-0.1.2}/src/bash_classify/commands/install.yaml +0 -0
  70. {bash_classify-0.1.0 → bash_classify-0.1.2}/src/bash_classify/commands/join.yaml +0 -0
  71. {bash_classify-0.1.0 → bash_classify-0.1.2}/src/bash_classify/commands/journalctl.yaml +0 -0
  72. {bash_classify-0.1.0 → bash_classify-0.1.2}/src/bash_classify/commands/jq.yaml +0 -0
  73. {bash_classify-0.1.0 → bash_classify-0.1.2}/src/bash_classify/commands/kill.yaml +0 -0
  74. {bash_classify-0.1.0 → bash_classify-0.1.2}/src/bash_classify/commands/killall.yaml +0 -0
  75. {bash_classify-0.1.0 → bash_classify-0.1.2}/src/bash_classify/commands/kubectl.yaml +0 -0
  76. {bash_classify-0.1.0 → bash_classify-0.1.2}/src/bash_classify/commands/less.yaml +0 -0
  77. {bash_classify-0.1.0 → bash_classify-0.1.2}/src/bash_classify/commands/ln.yaml +0 -0
  78. {bash_classify-0.1.0 → bash_classify-0.1.2}/src/bash_classify/commands/ls.yaml +0 -0
  79. {bash_classify-0.1.0 → bash_classify-0.1.2}/src/bash_classify/commands/make.yaml +0 -0
  80. {bash_classify-0.1.0 → bash_classify-0.1.2}/src/bash_classify/commands/md5sum.yaml +0 -0
  81. {bash_classify-0.1.0 → bash_classify-0.1.2}/src/bash_classify/commands/mkdir.yaml +0 -0
  82. {bash_classify-0.1.0 → bash_classify-0.1.2}/src/bash_classify/commands/more.yaml +0 -0
  83. {bash_classify-0.1.0 → bash_classify-0.1.2}/src/bash_classify/commands/mv.yaml +0 -0
  84. {bash_classify-0.1.0 → bash_classify-0.1.2}/src/bash_classify/commands/netstat.yaml +0 -0
  85. {bash_classify-0.1.0 → bash_classify-0.1.2}/src/bash_classify/commands/nice.yaml +0 -0
  86. {bash_classify-0.1.0 → bash_classify-0.1.2}/src/bash_classify/commands/nl.yaml +0 -0
  87. {bash_classify-0.1.0 → bash_classify-0.1.2}/src/bash_classify/commands/node.yaml +0 -0
  88. {bash_classify-0.1.0 → bash_classify-0.1.2}/src/bash_classify/commands/nohup.yaml +0 -0
  89. {bash_classify-0.1.0 → bash_classify-0.1.2}/src/bash_classify/commands/npm.yaml +0 -0
  90. {bash_classify-0.1.0 → bash_classify-0.1.2}/src/bash_classify/commands/nslookup.yaml +0 -0
  91. {bash_classify-0.1.0 → bash_classify-0.1.2}/src/bash_classify/commands/paste.yaml +0 -0
  92. {bash_classify-0.1.0 → bash_classify-0.1.2}/src/bash_classify/commands/ping.yaml +0 -0
  93. {bash_classify-0.1.0 → bash_classify-0.1.2}/src/bash_classify/commands/pip.yaml +0 -0
  94. {bash_classify-0.1.0 → bash_classify-0.1.2}/src/bash_classify/commands/pip3.yaml +0 -0
  95. {bash_classify-0.1.0 → bash_classify-0.1.2}/src/bash_classify/commands/pkill.yaml +0 -0
  96. {bash_classify-0.1.0 → bash_classify-0.1.2}/src/bash_classify/commands/poetry.yaml +0 -0
  97. {bash_classify-0.1.0 → bash_classify-0.1.2}/src/bash_classify/commands/printenv.yaml +0 -0
  98. {bash_classify-0.1.0 → bash_classify-0.1.2}/src/bash_classify/commands/printf.yaml +0 -0
  99. {bash_classify-0.1.0 → bash_classify-0.1.2}/src/bash_classify/commands/ps.yaml +0 -0
  100. {bash_classify-0.1.0 → bash_classify-0.1.2}/src/bash_classify/commands/pwd.yaml +0 -0
  101. {bash_classify-0.1.0 → bash_classify-0.1.2}/src/bash_classify/commands/python.yaml +0 -0
  102. {bash_classify-0.1.0 → bash_classify-0.1.2}/src/bash_classify/commands/python3.yaml +0 -0
  103. {bash_classify-0.1.0 → bash_classify-0.1.2}/src/bash_classify/commands/read.yaml +0 -0
  104. {bash_classify-0.1.0 → bash_classify-0.1.2}/src/bash_classify/commands/readlink.yaml +0 -0
  105. {bash_classify-0.1.0 → bash_classify-0.1.2}/src/bash_classify/commands/realpath.yaml +0 -0
  106. {bash_classify-0.1.0 → bash_classify-0.1.2}/src/bash_classify/commands/rev.yaml +0 -0
  107. {bash_classify-0.1.0 → bash_classify-0.1.2}/src/bash_classify/commands/rm.yaml +0 -0
  108. {bash_classify-0.1.0 → bash_classify-0.1.2}/src/bash_classify/commands/rsync.yaml +0 -0
  109. {bash_classify-0.1.0 → bash_classify-0.1.2}/src/bash_classify/commands/scp.yaml +0 -0
  110. {bash_classify-0.1.0 → bash_classify-0.1.2}/src/bash_classify/commands/sed.yaml +0 -0
  111. {bash_classify-0.1.0 → bash_classify-0.1.2}/src/bash_classify/commands/seq.yaml +0 -0
  112. {bash_classify-0.1.0 → bash_classify-0.1.2}/src/bash_classify/commands/sh.yaml +0 -0
  113. {bash_classify-0.1.0 → bash_classify-0.1.2}/src/bash_classify/commands/sha1sum.yaml +0 -0
  114. {bash_classify-0.1.0 → bash_classify-0.1.2}/src/bash_classify/commands/sha256sum.yaml +0 -0
  115. {bash_classify-0.1.0 → bash_classify-0.1.2}/src/bash_classify/commands/sort.yaml +0 -0
  116. {bash_classify-0.1.0 → bash_classify-0.1.2}/src/bash_classify/commands/ss.yaml +0 -0
  117. {bash_classify-0.1.0 → bash_classify-0.1.2}/src/bash_classify/commands/ssh.yaml +0 -0
  118. {bash_classify-0.1.0 → bash_classify-0.1.2}/src/bash_classify/commands/stat.yaml +0 -0
  119. {bash_classify-0.1.0 → bash_classify-0.1.2}/src/bash_classify/commands/strace.yaml +0 -0
  120. {bash_classify-0.1.0 → bash_classify-0.1.2}/src/bash_classify/commands/sudo.yaml +0 -0
  121. {bash_classify-0.1.0 → bash_classify-0.1.2}/src/bash_classify/commands/systemctl.yaml +0 -0
  122. {bash_classify-0.1.0 → bash_classify-0.1.2}/src/bash_classify/commands/tac.yaml +0 -0
  123. {bash_classify-0.1.0 → bash_classify-0.1.2}/src/bash_classify/commands/tail.yaml +0 -0
  124. {bash_classify-0.1.0 → bash_classify-0.1.2}/src/bash_classify/commands/tar.yaml +0 -0
  125. {bash_classify-0.1.0 → bash_classify-0.1.2}/src/bash_classify/commands/tee.yaml +0 -0
  126. {bash_classify-0.1.0 → bash_classify-0.1.2}/src/bash_classify/commands/terraform.yaml +0 -0
  127. {bash_classify-0.1.0 → bash_classify-0.1.2}/src/bash_classify/commands/test.yaml +0 -0
  128. {bash_classify-0.1.0 → bash_classify-0.1.2}/src/bash_classify/commands/time.yaml +0 -0
  129. {bash_classify-0.1.0 → bash_classify-0.1.2}/src/bash_classify/commands/timeout.yaml +0 -0
  130. {bash_classify-0.1.0 → bash_classify-0.1.2}/src/bash_classify/commands/top.yaml +0 -0
  131. {bash_classify-0.1.0 → bash_classify-0.1.2}/src/bash_classify/commands/touch.yaml +0 -0
  132. {bash_classify-0.1.0 → bash_classify-0.1.2}/src/bash_classify/commands/tr.yaml +0 -0
  133. {bash_classify-0.1.0 → bash_classify-0.1.2}/src/bash_classify/commands/traceroute.yaml +0 -0
  134. {bash_classify-0.1.0 → bash_classify-0.1.2}/src/bash_classify/commands/true.yaml +0 -0
  135. {bash_classify-0.1.0 → bash_classify-0.1.2}/src/bash_classify/commands/type.yaml +0 -0
  136. {bash_classify-0.1.0 → bash_classify-0.1.2}/src/bash_classify/commands/uname.yaml +0 -0
  137. {bash_classify-0.1.0 → bash_classify-0.1.2}/src/bash_classify/commands/unexpand.yaml +0 -0
  138. {bash_classify-0.1.0 → bash_classify-0.1.2}/src/bash_classify/commands/uniq.yaml +0 -0
  139. {bash_classify-0.1.0 → bash_classify-0.1.2}/src/bash_classify/commands/unzip.yaml +0 -0
  140. {bash_classify-0.1.0 → bash_classify-0.1.2}/src/bash_classify/commands/uptime.yaml +0 -0
  141. {bash_classify-0.1.0 → bash_classify-0.1.2}/src/bash_classify/commands/uv.yaml +0 -0
  142. {bash_classify-0.1.0 → bash_classify-0.1.2}/src/bash_classify/commands/wc.yaml +0 -0
  143. {bash_classify-0.1.0 → bash_classify-0.1.2}/src/bash_classify/commands/wget.yaml +0 -0
  144. {bash_classify-0.1.0 → bash_classify-0.1.2}/src/bash_classify/commands/whereis.yaml +0 -0
  145. {bash_classify-0.1.0 → bash_classify-0.1.2}/src/bash_classify/commands/which.yaml +0 -0
  146. {bash_classify-0.1.0 → bash_classify-0.1.2}/src/bash_classify/commands/whoami.yaml +0 -0
  147. {bash_classify-0.1.0 → bash_classify-0.1.2}/src/bash_classify/commands/xargs.yaml +0 -0
  148. {bash_classify-0.1.0 → bash_classify-0.1.2}/src/bash_classify/commands/xmllint.yaml +0 -0
  149. {bash_classify-0.1.0 → bash_classify-0.1.2}/src/bash_classify/commands/yes.yaml +0 -0
  150. {bash_classify-0.1.0 → bash_classify-0.1.2}/src/bash_classify/commands/yq.yaml +0 -0
  151. {bash_classify-0.1.0 → bash_classify-0.1.2}/src/bash_classify/commands/zip.yaml +0 -0
  152. {bash_classify-0.1.0 → bash_classify-0.1.2}/src/bash_classify/commands/zsh.yaml +0 -0
  153. {bash_classify-0.1.0 → bash_classify-0.1.2}/src/bash_classify/database.py +0 -0
  154. {bash_classify-0.1.0 → bash_classify-0.1.2}/src/bash_classify/matcher.py +0 -0
  155. {bash_classify-0.1.0 → bash_classify-0.1.2}/src/bash_classify/models.py +0 -0
  156. {bash_classify-0.1.0 → bash_classify-0.1.2}/src/bash_classify/parser.py +0 -0
  157. {bash_classify-0.1.0 → bash_classify-0.1.2}/src/bash_classify/py.typed +0 -0
  158. {bash_classify-0.1.0 → bash_classify-0.1.2}/tests/__init__.py +0 -0
  159. {bash_classify-0.1.0 → bash_classify-0.1.2}/tests/conftest.py +0 -0
  160. {bash_classify-0.1.0 → bash_classify-0.1.2}/tests/test_classifier.py +0 -0
  161. {bash_classify-0.1.0 → bash_classify-0.1.2}/tests/test_cli.py +0 -0
  162. {bash_classify-0.1.0 → bash_classify-0.1.2}/tests/test_cli_serialization.py +0 -0
  163. {bash_classify-0.1.0 → bash_classify-0.1.2}/tests/test_database.py +0 -0
  164. {bash_classify-0.1.0 → bash_classify-0.1.2}/tests/test_matcher.py +0 -0
  165. {bash_classify-0.1.0 → bash_classify-0.1.2}/tests/test_models.py +0 -0
  166. {bash_classify-0.1.0 → bash_classify-0.1.2}/tests/test_parser.py +0 -0
  167. {bash_classify-0.1.0 → bash_classify-0.1.2}/tests/test_real_world.py +0 -0
  168. {bash_classify-0.1.0 → bash_classify-0.1.2}/tests/test_schema.py +0 -0
  169. {bash_classify-0.1.0 → bash_classify-0.1.2}/tests/test_smoke.py +0 -0
  170. {bash_classify-0.1.0 → bash_classify-0.1.2}/uv.lock +0 -0
@@ -0,0 +1,21 @@
1
+ {
2
+ "name": "bash-classify",
3
+ "description": "Bash command classifier with Claude Code plugin for auto-allowing readonly commands",
4
+ "metadata": {
5
+ "pluginRoot": "./coding-agent-plugins/claude-code"
6
+ },
7
+ "plugins": [
8
+ {
9
+ "name": "bash-classify-hook",
10
+ "description": "Auto-allows readonly bash commands in Claude Code using bash-classify",
11
+ "version": "0.1.2",
12
+ "author": {
13
+ "name": "Filip Procházka",
14
+ "url": "https://github.com/fprochazka"
15
+ },
16
+ "source": ".",
17
+ "category": "security",
18
+ "homepage": "https://github.com/fprochazka/bash-classify"
19
+ }
20
+ ]
21
+ }
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: bash-classify
3
- Version: 0.1.0
3
+ Version: 0.1.2
4
4
  Summary: Classify bash commands as READONLY, WRITE, DANGEROUS, or UNKNOWN
5
5
  Project-URL: Homepage, https://github.com/fprochazka/bash-classify
6
6
  Project-URL: Repository, https://github.com/fprochazka/bash-classify
@@ -61,35 +61,29 @@ $ echo 'find . -name "*.pyc" -delete' | bash-classify | jq '.classification'
61
61
  "DANGEROUS"
62
62
  ```
63
63
 
64
- ## Claude Code hook
65
-
66
- Install as a Claude Code hook to auto-allow read-only commands and require approval for everything else:
67
-
68
- ```json
69
- {
70
- "hooks": {
71
- "PreToolUse": [
72
- {
73
- "matcher": "Bash",
74
- "hooks": [
75
- {
76
- "type": "command",
77
- "command": "echo \"$CLAUDE_TOOL_INPUT\" | jq -r '.command' | bash-classify",
78
- "timeout": 5000,
79
- "on_output": [
80
- {
81
- "matcher": "\"classification\": \"READONLY\"",
82
- "action": "approve"
83
- }
84
- ]
85
- }
86
- ]
87
- }
88
- ]
89
- }
90
- }
64
+ ## Claude Code plugin
65
+
66
+ The repo includes a Claude Code plugin that auto-allows readonly bash commands via a `PreToolUse` hook.
67
+
68
+ ```bash
69
+ # Install the bash-classify CLI
70
+ uv tool install bash-classify
71
+
72
+ # Add the marketplace and install the plugin
73
+ claude plugin marketplace add fprochazka/bash-classify
74
+ claude plugin install bash-classify-hook@fprochazka-bash-classify
91
75
  ```
92
76
 
77
+ To upgrade after a new release:
78
+
79
+ ```bash
80
+ uv tool upgrade bash-classify
81
+ claude plugin marketplace update fprochazka-bash-classify
82
+ claude plugin update bash-classify-hook@fprochazka-bash-classify
83
+ ```
84
+
85
+ Once installed, any Bash tool call classified as `READONLY` is auto-approved — no permission prompt. Everything else (WRITE, DANGEROUS, UNKNOWN) still requires confirmation.
86
+
93
87
  ## Command database
94
88
 
95
89
  The classification database includes 120+ command definitions covering common Unix utilities, package managers, container tools, cloud CLIs, and more.
@@ -142,6 +136,24 @@ uv run pytest
142
136
 
143
137
  To add or modify command definitions, see [docs/classification-guidance.md](docs/classification-guidance.md). All YAML files in `src/bash_classify/commands/` are validated against a [JSON Schema](schemas/command.schema.json) — your IDE will provide autocomplete if it supports the `# $schema:` comment.
144
138
 
139
+ ## Releasing
140
+
141
+ Version is derived automatically from git tags via `hatch-vcs` — no manual version bumping needed.
142
+
143
+ Before tagging, bump the version in both plugin manifest files:
144
+
145
+ - `coding-agent-plugins/claude-code/.claude-plugin/plugin.json`
146
+ - `.claude-plugin/marketplace.json`
147
+
148
+ Then tag and push:
149
+
150
+ ```bash
151
+ git tag v<version>
152
+ git push origin v<version>
153
+ ```
154
+
155
+ The `publish.yml` GitHub Action builds and publishes to PyPI automatically via trusted publishing.
156
+
145
157
  ## License
146
158
 
147
159
  [MIT](LICENSE)
@@ -32,35 +32,29 @@ $ echo 'find . -name "*.pyc" -delete' | bash-classify | jq '.classification'
32
32
  "DANGEROUS"
33
33
  ```
34
34
 
35
- ## Claude Code hook
36
-
37
- Install as a Claude Code hook to auto-allow read-only commands and require approval for everything else:
38
-
39
- ```json
40
- {
41
- "hooks": {
42
- "PreToolUse": [
43
- {
44
- "matcher": "Bash",
45
- "hooks": [
46
- {
47
- "type": "command",
48
- "command": "echo \"$CLAUDE_TOOL_INPUT\" | jq -r '.command' | bash-classify",
49
- "timeout": 5000,
50
- "on_output": [
51
- {
52
- "matcher": "\"classification\": \"READONLY\"",
53
- "action": "approve"
54
- }
55
- ]
56
- }
57
- ]
58
- }
59
- ]
60
- }
61
- }
35
+ ## Claude Code plugin
36
+
37
+ The repo includes a Claude Code plugin that auto-allows readonly bash commands via a `PreToolUse` hook.
38
+
39
+ ```bash
40
+ # Install the bash-classify CLI
41
+ uv tool install bash-classify
42
+
43
+ # Add the marketplace and install the plugin
44
+ claude plugin marketplace add fprochazka/bash-classify
45
+ claude plugin install bash-classify-hook@fprochazka-bash-classify
62
46
  ```
63
47
 
48
+ To upgrade after a new release:
49
+
50
+ ```bash
51
+ uv tool upgrade bash-classify
52
+ claude plugin marketplace update fprochazka-bash-classify
53
+ claude plugin update bash-classify-hook@fprochazka-bash-classify
54
+ ```
55
+
56
+ Once installed, any Bash tool call classified as `READONLY` is auto-approved — no permission prompt. Everything else (WRITE, DANGEROUS, UNKNOWN) still requires confirmation.
57
+
64
58
  ## Command database
65
59
 
66
60
  The classification database includes 120+ command definitions covering common Unix utilities, package managers, container tools, cloud CLIs, and more.
@@ -113,6 +107,24 @@ uv run pytest
113
107
 
114
108
  To add or modify command definitions, see [docs/classification-guidance.md](docs/classification-guidance.md). All YAML files in `src/bash_classify/commands/` are validated against a [JSON Schema](schemas/command.schema.json) — your IDE will provide autocomplete if it supports the `# $schema:` comment.
115
109
 
110
+ ## Releasing
111
+
112
+ Version is derived automatically from git tags via `hatch-vcs` — no manual version bumping needed.
113
+
114
+ Before tagging, bump the version in both plugin manifest files:
115
+
116
+ - `coding-agent-plugins/claude-code/.claude-plugin/plugin.json`
117
+ - `.claude-plugin/marketplace.json`
118
+
119
+ Then tag and push:
120
+
121
+ ```bash
122
+ git tag v<version>
123
+ git push origin v<version>
124
+ ```
125
+
126
+ The `publish.yml` GitHub Action builds and publishes to PyPI automatically via trusted publishing.
127
+
116
128
  ## License
117
129
 
118
130
  [MIT](LICENSE)
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bash-classify-hook",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "description": "Auto-allows readonly bash commands in Claude Code using bash-classify",
5
5
  "author": {
6
6
  "name": "Filip Prochazka"
@@ -36,7 +36,7 @@ classification=$(echo "$classification_output" | jq -r '.classification // empty
36
36
 
37
37
  if [[ "$classification" == "READONLY" ]]; then
38
38
  # Auto-allow readonly commands
39
- echo '{"hookSpecificOutput":{"permissionDecision":"allow"}}'
39
+ echo '{"hookSpecificOutput":{"hookEventName":"PreToolUse","permissionDecision":"allow"}}'
40
40
  fi
41
41
 
42
42
  # For anything else (WRITE, DANGEROUS, UNKNOWN), output nothing
@@ -95,7 +95,33 @@ def main() -> None:
95
95
  1 - parse error (invalid bash syntax)
96
96
  2 - internal error
97
97
  """
98
+ if len(sys.argv) > 1 and sys.argv[1] in ("-h", "--help"):
99
+ print("Usage: bash-classify < command")
100
+ print(" echo 'ls -la' | bash-classify")
101
+ print()
102
+ print("Reads a bash expression from stdin, classifies it, and outputs JSON.")
103
+ print()
104
+ print("Exit codes:")
105
+ print(" 0 successfully classified")
106
+ print(" 1 empty input")
107
+ print(" 2 internal error")
108
+ sys.exit(0)
109
+
110
+ if len(sys.argv) > 1 and sys.argv[1] in ("-v", "--version"):
111
+ from importlib.metadata import version
112
+
113
+ print(f"bash-classify {version('bash-classify')}")
114
+ sys.exit(0)
115
+
98
116
  try:
117
+ import select
118
+
119
+ # Timeout if no data arrives within 5 seconds
120
+ ready, _, _ = select.select([sys.stdin], [], [], 5.0)
121
+ if not ready:
122
+ print("bash-classify: timed out waiting for input on stdin (use --help for usage)", file=sys.stderr)
123
+ sys.exit(1)
124
+
99
125
  expression = sys.stdin.read().strip()
100
126
  if not expression:
101
127
  sys.exit(1)
@@ -1,13 +0,0 @@
1
- {
2
- "name": "bash-classify",
3
- "description": "Bash command classifier with Claude Code plugin for auto-allowing readonly commands",
4
- "metadata": {
5
- "pluginRoot": "./coding-agent-plugins/claude-code"
6
- },
7
- "plugins": [
8
- {
9
- "name": "bash-classify-hook",
10
- "source": "."
11
- }
12
- ]
13
- }
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes