bash-classify 0.2.3__tar.gz → 0.3.0__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.
- {bash_classify-0.2.3 → bash_classify-0.3.0}/.claude-plugin/marketplace.json +3 -3
- {bash_classify-0.2.3 → bash_classify-0.3.0}/PKG-INFO +19 -6
- {bash_classify-0.2.3 → bash_classify-0.3.0}/README.md +18 -5
- {bash_classify-0.2.3 → bash_classify-0.3.0}/SPEC.md +48 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/coding-agent-plugins/claude-code/.claude-plugin/plugin.json +2 -2
- {bash_classify-0.2.3 → bash_classify-0.3.0}/coding-agent-plugins/claude-code/hooks/classify-bash.sh +5 -5
- {bash_classify-0.2.3 → bash_classify-0.3.0}/docs/classification-guidance.md +43 -1
- {bash_classify-0.2.3 → bash_classify-0.3.0}/schemas/command.schema.json +17 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/src/bash_classify/__init__.py +2 -1
- {bash_classify-0.2.3 → bash_classify-0.3.0}/src/bash_classify/classifier.py +14 -1
- {bash_classify-0.2.3 → bash_classify-0.3.0}/src/bash_classify/cli.py +3 -0
- bash_classify-0.3.0/src/bash_classify/commands/agent-browser.yaml +9 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/src/bash_classify/commands/black.yaml +1 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/src/bash_classify/commands/brew.yaml +4 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/src/bash_classify/commands/cargo.yaml +14 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/src/bash_classify/commands/docker.yaml +4 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/src/bash_classify/commands/git.yaml +28 -10
- bash_classify-0.3.0/src/bash_classify/commands/glab-discussion.yaml +21 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/src/bash_classify/commands/go.yaml +4 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/src/bash_classify/commands/gunzip.yaml +1 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/src/bash_classify/commands/isort.yaml +1 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/src/bash_classify/commands/kubectl.yaml +3 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/src/bash_classify/commands/mkdir.yaml +1 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/src/bash_classify/commands/npm.yaml +4 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/src/bash_classify/commands/pip.yaml +2 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/src/bash_classify/commands/pip3.yaml +2 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/src/bash_classify/commands/pipx.yaml +2 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/src/bash_classify/commands/poetry.yaml +7 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/src/bash_classify/commands/ruff.yaml +4 -2
- {bash_classify-0.2.3 → bash_classify-0.3.0}/src/bash_classify/commands/tar.yaml +1 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/src/bash_classify/commands/touch.yaml +1 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/src/bash_classify/commands/tsc.yaml +1 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/src/bash_classify/commands/unzip.yaml +1 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/src/bash_classify/commands/uv.yaml +16 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/src/bash_classify/commands/yarn.yaml +3 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/src/bash_classify/commands/zip.yaml +1 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/src/bash_classify/database.py +11 -1
- {bash_classify-0.2.3 → bash_classify-0.3.0}/src/bash_classify/matcher.py +99 -8
- {bash_classify-0.2.3 → bash_classify-0.3.0}/src/bash_classify/models.py +34 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/tests/test_classifier.py +76 -1
- {bash_classify-0.2.3 → bash_classify-0.3.0}/tests/test_cli_serialization.py +77 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/tests/test_matcher.py +128 -1
- {bash_classify-0.2.3 → bash_classify-0.3.0}/tests/test_models.py +25 -1
- {bash_classify-0.2.3 → bash_classify-0.3.0}/.claude/rules/command-database.md +0 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/.editorconfig +0 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/.github/workflows/ci.yml +0 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/.github/workflows/publish.yml +0 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/.gitignore +0 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/.python-version +0 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/CLAUDE.md +0 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/LICENSE +0 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/coding-agent-plugins/claude-code/hooks/hooks.json +0 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/pyproject.toml +0 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/ruff.toml +0 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/src/bash_classify/__main__.py +0 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/src/bash_classify/commands/apt.yaml +0 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/src/bash_classify/commands/awk.yaml +0 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/src/bash_classify/commands/basename.yaml +0 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/src/bash_classify/commands/bash-classify.yaml +0 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/src/bash_classify/commands/bash.yaml +0 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/src/bash_classify/commands/builtin.yaml +0 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/src/bash_classify/commands/cat.yaml +0 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/src/bash_classify/commands/chgrp.yaml +0 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/src/bash_classify/commands/chmod.yaml +0 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/src/bash_classify/commands/chown.yaml +0 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/src/bash_classify/commands/column.yaml +0 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/src/bash_classify/commands/comm.yaml +0 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/src/bash_classify/commands/command.yaml +0 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/src/bash_classify/commands/cp.yaml +0 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/src/bash_classify/commands/curl.yaml +0 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/src/bash_classify/commands/cut.yaml +0 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/src/bash_classify/commands/date.yaml +0 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/src/bash_classify/commands/df.yaml +0 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/src/bash_classify/commands/diff.yaml +0 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/src/bash_classify/commands/dig.yaml +0 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/src/bash_classify/commands/dirname.yaml +0 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/src/bash_classify/commands/du.yaml +0 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/src/bash_classify/commands/echo.yaml +0 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/src/bash_classify/commands/env.yaml +0 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/src/bash_classify/commands/eslint.yaml +0 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/src/bash_classify/commands/expand.yaml +0 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/src/bash_classify/commands/false.yaml +0 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/src/bash_classify/commands/file.yaml +0 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/src/bash_classify/commands/find.yaml +0 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/src/bash_classify/commands/fmt.yaml +0 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/src/bash_classify/commands/fold.yaml +0 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/src/bash_classify/commands/free.yaml +0 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/src/bash_classify/commands/gawk.yaml +0 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/src/bash_classify/commands/gcloud.yaml +0 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/src/bash_classify/commands/gh.yaml +0 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/src/bash_classify/commands/glab.yaml +0 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/src/bash_classify/commands/gradle.yaml +0 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/src/bash_classify/commands/gradlew.yaml +0 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/src/bash_classify/commands/grep.yaml +0 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/src/bash_classify/commands/groups.yaml +0 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/src/bash_classify/commands/gzip.yaml +0 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/src/bash_classify/commands/hadolint.yaml +0 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/src/bash_classify/commands/head.yaml +0 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/src/bash_classify/commands/helm.yaml +0 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/src/bash_classify/commands/hostname.yaml +0 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/src/bash_classify/commands/id.yaml +0 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/src/bash_classify/commands/install.yaml +0 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/src/bash_classify/commands/java.yaml +0 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/src/bash_classify/commands/javac.yaml +0 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/src/bash_classify/commands/join.yaml +0 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/src/bash_classify/commands/journalctl.yaml +0 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/src/bash_classify/commands/jq.yaml +0 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/src/bash_classify/commands/kill.yaml +0 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/src/bash_classify/commands/killall.yaml +0 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/src/bash_classify/commands/less.yaml +0 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/src/bash_classify/commands/ln.yaml +0 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/src/bash_classify/commands/ls.yaml +0 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/src/bash_classify/commands/make.yaml +0 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/src/bash_classify/commands/md5sum.yaml +0 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/src/bash_classify/commands/more.yaml +0 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/src/bash_classify/commands/mv.yaml +0 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/src/bash_classify/commands/mvn.yaml +0 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/src/bash_classify/commands/mvnw.yaml +0 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/src/bash_classify/commands/mypy.yaml +0 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/src/bash_classify/commands/netstat.yaml +0 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/src/bash_classify/commands/nice.yaml +0 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/src/bash_classify/commands/nl.yaml +0 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/src/bash_classify/commands/node.yaml +0 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/src/bash_classify/commands/nohup.yaml +0 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/src/bash_classify/commands/npx.yaml +0 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/src/bash_classify/commands/nslookup.yaml +0 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/src/bash_classify/commands/paste.yaml +0 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/src/bash_classify/commands/ping.yaml +0 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/src/bash_classify/commands/pkill.yaml +0 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/src/bash_classify/commands/prettier.yaml +0 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/src/bash_classify/commands/printenv.yaml +0 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/src/bash_classify/commands/printf.yaml +0 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/src/bash_classify/commands/ps.yaml +0 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/src/bash_classify/commands/pwd.yaml +0 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/src/bash_classify/commands/pytest.yaml +0 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/src/bash_classify/commands/python.yaml +0 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/src/bash_classify/commands/python3.yaml +0 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/src/bash_classify/commands/read.yaml +0 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/src/bash_classify/commands/readlink.yaml +0 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/src/bash_classify/commands/realpath.yaml +0 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/src/bash_classify/commands/rev.yaml +0 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/src/bash_classify/commands/rg.yaml +0 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/src/bash_classify/commands/rm.yaml +0 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/src/bash_classify/commands/rsync.yaml +0 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/src/bash_classify/commands/scp.yaml +0 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/src/bash_classify/commands/sed.yaml +0 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/src/bash_classify/commands/seq.yaml +0 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/src/bash_classify/commands/sh.yaml +0 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/src/bash_classify/commands/sha1sum.yaml +0 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/src/bash_classify/commands/sha256sum.yaml +0 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/src/bash_classify/commands/shellcheck.yaml +0 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/src/bash_classify/commands/sort.yaml +0 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/src/bash_classify/commands/ss.yaml +0 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/src/bash_classify/commands/ssh.yaml +0 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/src/bash_classify/commands/stat.yaml +0 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/src/bash_classify/commands/strace.yaml +0 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/src/bash_classify/commands/sudo.yaml +0 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/src/bash_classify/commands/systemctl.yaml +0 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/src/bash_classify/commands/tac.yaml +0 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/src/bash_classify/commands/tail.yaml +0 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/src/bash_classify/commands/tee.yaml +0 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/src/bash_classify/commands/terraform.yaml +0 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/src/bash_classify/commands/test.yaml +0 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/src/bash_classify/commands/time.yaml +0 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/src/bash_classify/commands/timeout.yaml +0 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/src/bash_classify/commands/top.yaml +0 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/src/bash_classify/commands/tr.yaml +0 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/src/bash_classify/commands/traceroute.yaml +0 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/src/bash_classify/commands/true.yaml +0 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/src/bash_classify/commands/type.yaml +0 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/src/bash_classify/commands/uname.yaml +0 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/src/bash_classify/commands/unexpand.yaml +0 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/src/bash_classify/commands/uniq.yaml +0 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/src/bash_classify/commands/uptime.yaml +0 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/src/bash_classify/commands/wc.yaml +0 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/src/bash_classify/commands/wget.yaml +0 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/src/bash_classify/commands/whereis.yaml +0 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/src/bash_classify/commands/which.yaml +0 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/src/bash_classify/commands/whoami.yaml +0 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/src/bash_classify/commands/xargs.yaml +0 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/src/bash_classify/commands/xmllint.yaml +0 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/src/bash_classify/commands/yes.yaml +0 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/src/bash_classify/commands/yq.yaml +0 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/src/bash_classify/commands/zsh.yaml +0 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/src/bash_classify/parser.py +0 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/src/bash_classify/py.typed +0 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/tests/__init__.py +0 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/tests/conftest.py +0 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/tests/test_cli.py +0 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/tests/test_database.py +0 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/tests/test_parser.py +0 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/tests/test_real_world.py +0 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/tests/test_schema.py +0 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/tests/test_smoke.py +0 -0
- {bash_classify-0.2.3 → bash_classify-0.3.0}/uv.lock +0 -0
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "fprochazka-bash-classify",
|
|
3
|
-
"description": "Bash command classifier with Claude Code plugin for auto-allowing
|
|
3
|
+
"description": "Bash command classifier with Claude Code plugin for auto-allowing low-risk commands",
|
|
4
4
|
"owner": {
|
|
5
5
|
"name": "Filip Procházka"
|
|
6
6
|
},
|
|
7
7
|
"plugins": [
|
|
8
8
|
{
|
|
9
9
|
"name": "bash-classify-hook",
|
|
10
|
-
"description": "Auto-allows
|
|
11
|
-
"version": "0.
|
|
10
|
+
"description": "Auto-allows low-risk bash commands in Claude Code using bash-classify",
|
|
11
|
+
"version": "0.3.0",
|
|
12
12
|
"author": {
|
|
13
13
|
"name": "Filip Procházka",
|
|
14
14
|
"url": "https://github.com/fprochazka"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: bash-classify
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.3.0
|
|
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
|
|
@@ -33,9 +33,9 @@ Classify bash commands by their side-effect risk level.
|
|
|
33
33
|
|
|
34
34
|
## What it does
|
|
35
35
|
|
|
36
|
-
bash-classify parses bash expressions using tree-sitter, classifies each command against a database of 120+ known commands, and outputs a structured JSON verdict. Commands are classified
|
|
36
|
+
bash-classify parses bash expressions using tree-sitter, classifies each command against a database of 120+ known commands, and outputs a structured JSON verdict. Commands are classified along two axes: **classification** (`READONLY`, `LOCAL_EFFECTS`, `EXTERNAL_EFFECTS`, `DANGEROUS`, `UNKNOWN`) describing what kind of effects a command has, and **risk** (`LOW`, `MEDIUM`, `HIGH`) describing how worried you should be.
|
|
37
37
|
|
|
38
|
-
Designed primarily as a [Claude Code](https://docs.anthropic.com/en/docs/claude-code) hook to automatically allow
|
|
38
|
+
Designed primarily as a [Claude Code](https://docs.anthropic.com/en/docs/claude-code) hook to automatically allow low-risk commands while flagging risky ones for human review.
|
|
39
39
|
|
|
40
40
|
## Installation
|
|
41
41
|
|
|
@@ -63,7 +63,7 @@ $ echo 'find . -name "*.pyc" -delete' | bash-classify | jq '.classification'
|
|
|
63
63
|
|
|
64
64
|
## Claude Code plugin
|
|
65
65
|
|
|
66
|
-
The repo includes a Claude Code plugin that auto-allows
|
|
66
|
+
The repo includes a Claude Code plugin that auto-allows low-risk bash commands via a `PreToolUse` hook.
|
|
67
67
|
|
|
68
68
|
```bash
|
|
69
69
|
# Install the bash-classify CLI
|
|
@@ -82,7 +82,7 @@ claude plugin marketplace update fprochazka-bash-classify
|
|
|
82
82
|
claude plugin update bash-classify-hook@fprochazka-bash-classify
|
|
83
83
|
```
|
|
84
84
|
|
|
85
|
-
Once installed, any Bash tool call
|
|
85
|
+
Once installed, any Bash tool call with `risk: LOW` is auto-approved — no permission prompt. This includes all `READONLY` commands plus safe routine operations like `git add`, `git commit`, `mkdir`, package installs, code formatters, and more. Commands with `MEDIUM` or `HIGH` risk still require confirmation.
|
|
86
86
|
|
|
87
87
|
## Command database
|
|
88
88
|
|
|
@@ -95,12 +95,24 @@ The classification database includes 120+ command definitions covering common Un
|
|
|
95
95
|
|
|
96
96
|
| Level | Description | Examples |
|
|
97
97
|
|---|---|---|
|
|
98
|
-
| `READONLY` | No side effects
|
|
98
|
+
| `READONLY` | No side effects | `ls`, `cat`, `grep`, `kubectl get` |
|
|
99
99
|
| `LOCAL_EFFECTS` | Modifies local files or state only | `git add`, `git commit`, `cp`, `mkdir`, `pytest` |
|
|
100
100
|
| `EXTERNAL_EFFECTS` | Interacts with external systems | `git push`, `kubectl apply`, `curl -d` |
|
|
101
101
|
| `DANGEROUS` | Destructive, system-wide, or irreversible | `rm -rf`, `git push --force`, `chmod` |
|
|
102
102
|
| `UNKNOWN` | Command not in database | Any unrecognized command |
|
|
103
103
|
|
|
104
|
+
## Risk levels
|
|
105
|
+
|
|
106
|
+
Each command also gets a **risk** rating, orthogonal to classification:
|
|
107
|
+
|
|
108
|
+
| Risk | Description | Examples |
|
|
109
|
+
|---|---|---|
|
|
110
|
+
| `LOW` | Safe, routine operation — auto-approved | `ls`, `git add`, `git commit`, `mkdir`, `ruff format` |
|
|
111
|
+
| `MEDIUM` | Normal caution warranted | `git push`, `cp`, `npm run`, `git rebase` |
|
|
112
|
+
| `HIGH` | Dangerous or unknown — always requires confirmation | `rm -rf`, `git push --force`, unknown commands |
|
|
113
|
+
|
|
114
|
+
Risk defaults are derived from classification (`READONLY`→LOW, `LOCAL_EFFECTS`→MEDIUM, `EXTERNAL_EFFECTS`→MEDIUM, `DANGEROUS`/`UNKNOWN`→HIGH) but can be overridden per command, subcommand, or option in the YAML database.
|
|
115
|
+
|
|
104
116
|
## How it works
|
|
105
117
|
|
|
106
118
|
- **Tree-sitter parsing** -- bash expressions are parsed into an AST for accurate command extraction, handling pipes, subshells, and command substitution
|
|
@@ -115,6 +127,7 @@ from bash_classify import classify_expression
|
|
|
115
127
|
|
|
116
128
|
result = classify_expression("kubectl get pods")
|
|
117
129
|
print(result.classification) # Classification.READONLY
|
|
130
|
+
print(result.risk) # Risk.LOW
|
|
118
131
|
```
|
|
119
132
|
|
|
120
133
|
See [SPEC.md](SPEC.md) for the full specification.
|
|
@@ -4,9 +4,9 @@ Classify bash commands by their side-effect risk level.
|
|
|
4
4
|
|
|
5
5
|
## What it does
|
|
6
6
|
|
|
7
|
-
bash-classify parses bash expressions using tree-sitter, classifies each command against a database of 120+ known commands, and outputs a structured JSON verdict. Commands are classified
|
|
7
|
+
bash-classify parses bash expressions using tree-sitter, classifies each command against a database of 120+ known commands, and outputs a structured JSON verdict. Commands are classified along two axes: **classification** (`READONLY`, `LOCAL_EFFECTS`, `EXTERNAL_EFFECTS`, `DANGEROUS`, `UNKNOWN`) describing what kind of effects a command has, and **risk** (`LOW`, `MEDIUM`, `HIGH`) describing how worried you should be.
|
|
8
8
|
|
|
9
|
-
Designed primarily as a [Claude Code](https://docs.anthropic.com/en/docs/claude-code) hook to automatically allow
|
|
9
|
+
Designed primarily as a [Claude Code](https://docs.anthropic.com/en/docs/claude-code) hook to automatically allow low-risk commands while flagging risky ones for human review.
|
|
10
10
|
|
|
11
11
|
## Installation
|
|
12
12
|
|
|
@@ -34,7 +34,7 @@ $ echo 'find . -name "*.pyc" -delete' | bash-classify | jq '.classification'
|
|
|
34
34
|
|
|
35
35
|
## Claude Code plugin
|
|
36
36
|
|
|
37
|
-
The repo includes a Claude Code plugin that auto-allows
|
|
37
|
+
The repo includes a Claude Code plugin that auto-allows low-risk bash commands via a `PreToolUse` hook.
|
|
38
38
|
|
|
39
39
|
```bash
|
|
40
40
|
# Install the bash-classify CLI
|
|
@@ -53,7 +53,7 @@ claude plugin marketplace update fprochazka-bash-classify
|
|
|
53
53
|
claude plugin update bash-classify-hook@fprochazka-bash-classify
|
|
54
54
|
```
|
|
55
55
|
|
|
56
|
-
Once installed, any Bash tool call
|
|
56
|
+
Once installed, any Bash tool call with `risk: LOW` is auto-approved — no permission prompt. This includes all `READONLY` commands plus safe routine operations like `git add`, `git commit`, `mkdir`, package installs, code formatters, and more. Commands with `MEDIUM` or `HIGH` risk still require confirmation.
|
|
57
57
|
|
|
58
58
|
## Command database
|
|
59
59
|
|
|
@@ -66,12 +66,24 @@ The classification database includes 120+ command definitions covering common Un
|
|
|
66
66
|
|
|
67
67
|
| Level | Description | Examples |
|
|
68
68
|
|---|---|---|
|
|
69
|
-
| `READONLY` | No side effects
|
|
69
|
+
| `READONLY` | No side effects | `ls`, `cat`, `grep`, `kubectl get` |
|
|
70
70
|
| `LOCAL_EFFECTS` | Modifies local files or state only | `git add`, `git commit`, `cp`, `mkdir`, `pytest` |
|
|
71
71
|
| `EXTERNAL_EFFECTS` | Interacts with external systems | `git push`, `kubectl apply`, `curl -d` |
|
|
72
72
|
| `DANGEROUS` | Destructive, system-wide, or irreversible | `rm -rf`, `git push --force`, `chmod` |
|
|
73
73
|
| `UNKNOWN` | Command not in database | Any unrecognized command |
|
|
74
74
|
|
|
75
|
+
## Risk levels
|
|
76
|
+
|
|
77
|
+
Each command also gets a **risk** rating, orthogonal to classification:
|
|
78
|
+
|
|
79
|
+
| Risk | Description | Examples |
|
|
80
|
+
|---|---|---|
|
|
81
|
+
| `LOW` | Safe, routine operation — auto-approved | `ls`, `git add`, `git commit`, `mkdir`, `ruff format` |
|
|
82
|
+
| `MEDIUM` | Normal caution warranted | `git push`, `cp`, `npm run`, `git rebase` |
|
|
83
|
+
| `HIGH` | Dangerous or unknown — always requires confirmation | `rm -rf`, `git push --force`, unknown commands |
|
|
84
|
+
|
|
85
|
+
Risk defaults are derived from classification (`READONLY`→LOW, `LOCAL_EFFECTS`→MEDIUM, `EXTERNAL_EFFECTS`→MEDIUM, `DANGEROUS`/`UNKNOWN`→HIGH) but can be overridden per command, subcommand, or option in the YAML database.
|
|
86
|
+
|
|
75
87
|
## How it works
|
|
76
88
|
|
|
77
89
|
- **Tree-sitter parsing** -- bash expressions are parsed into an AST for accurate command extraction, handling pipes, subshells, and command substitution
|
|
@@ -86,6 +98,7 @@ from bash_classify import classify_expression
|
|
|
86
98
|
|
|
87
99
|
result = classify_expression("kubectl get pods")
|
|
88
100
|
print(result.classification) # Classification.READONLY
|
|
101
|
+
print(result.risk) # Risk.LOW
|
|
89
102
|
```
|
|
90
103
|
|
|
91
104
|
See [SPEC.md](SPEC.md) for the full specification.
|
|
@@ -200,6 +200,54 @@ $ echo 'sh -c "ls /tmp | grep log"' | bash-classify
|
|
|
200
200
|
| `DANGEROUS` | Destructive, hard to reverse, or affects critical systems |
|
|
201
201
|
| `UNKNOWN` | Command or subcommand not in database |
|
|
202
202
|
|
|
203
|
+
### Risk levels
|
|
204
|
+
|
|
205
|
+
Each command also receives a risk level, used to distinguish routine operations from high-stakes ones within the same classification tier.
|
|
206
|
+
|
|
207
|
+
| Level | Meaning |
|
|
208
|
+
|---|---|
|
|
209
|
+
| `LOW` | Safe routine operation, suitable for auto-allowing |
|
|
210
|
+
| `MEDIUM` | Standard operation, may deserve review |
|
|
211
|
+
| `HIGH` | High-stakes or irreversible, always requires confirmation |
|
|
212
|
+
|
|
213
|
+
#### Default risk by classification
|
|
214
|
+
|
|
215
|
+
| Classification | Default risk |
|
|
216
|
+
|---|---|
|
|
217
|
+
| `READONLY` | `LOW` |
|
|
218
|
+
| `LOCAL_EFFECTS` | `MEDIUM` |
|
|
219
|
+
| `EXTERNAL_EFFECTS` | `MEDIUM` |
|
|
220
|
+
| `DANGEROUS` | `HIGH` (always, cannot be overridden) |
|
|
221
|
+
| `UNKNOWN` | `HIGH` (always, cannot be overridden) |
|
|
222
|
+
|
|
223
|
+
`DANGEROUS` and `UNKNOWN` commands are always clamped to `HIGH` regardless of any explicit `risk` field in the YAML definition.
|
|
224
|
+
|
|
225
|
+
#### Composite risk
|
|
226
|
+
|
|
227
|
+
The overall `risk` of a full expression is the **maximum** across all commands in the expression:
|
|
228
|
+
|
|
229
|
+
```
|
|
230
|
+
HIGH > MEDIUM > LOW
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
#### YAML `risk` field
|
|
234
|
+
|
|
235
|
+
The optional `risk` field can be set on commands, subcommands, and options in the database YAML. It works the same way as classification:
|
|
236
|
+
|
|
237
|
+
- **Command/subcommand level:** Sets the base risk for that command or subcommand.
|
|
238
|
+
- **Option level:** When the option is present, overrides the risk to this level (same semantics as classification `overrides`).
|
|
239
|
+
|
|
240
|
+
When no explicit `risk` is set, the default risk for the resolved classification is used.
|
|
241
|
+
|
|
242
|
+
#### Security elevations
|
|
243
|
+
|
|
244
|
+
Certain expression-level patterns elevate risk to at least `HIGH`:
|
|
245
|
+
|
|
246
|
+
- Writing to system paths (e.g. `/etc`, `/usr`)
|
|
247
|
+
- Redirecting to `/dev/tcp` or `/dev/udp`
|
|
248
|
+
- Backgrounding (`cmd &`)
|
|
249
|
+
- Output redirects to non-`/dev/null` targets
|
|
250
|
+
|
|
203
251
|
### Composite classification
|
|
204
252
|
|
|
205
253
|
The overall `classification` of a full expression is the **maximum severity** across all commands in the expression:
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "bash-classify-hook",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Auto-allows
|
|
3
|
+
"version": "0.3.0",
|
|
4
|
+
"description": "Auto-allows low-risk bash commands in Claude Code using bash-classify",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Filip Prochazka"
|
|
7
7
|
},
|
{bash_classify-0.2.3 → bash_classify-0.3.0}/coding-agent-plugins/claude-code/hooks/classify-bash.sh
RENAMED
|
@@ -31,14 +31,14 @@ if [[ -z "$classification_output" ]]; then
|
|
|
31
31
|
exit 0
|
|
32
32
|
fi
|
|
33
33
|
|
|
34
|
-
# Extract the top-level
|
|
35
|
-
|
|
34
|
+
# Extract the top-level risk
|
|
35
|
+
risk=$(echo "$classification_output" | jq -r '.risk // empty')
|
|
36
36
|
|
|
37
|
-
if [[ "$
|
|
38
|
-
# Auto-allow
|
|
37
|
+
if [[ "$risk" == "LOW" ]]; then
|
|
38
|
+
# Auto-allow low-risk commands
|
|
39
39
|
echo '{"hookSpecificOutput":{"hookEventName":"PreToolUse","permissionDecision":"allow"}}'
|
|
40
40
|
fi
|
|
41
41
|
|
|
42
|
-
# For anything else (
|
|
42
|
+
# For anything else (MEDIUM, HIGH), output nothing
|
|
43
43
|
# — this lets the normal permission flow handle it
|
|
44
44
|
exit 0
|
|
@@ -368,7 +368,49 @@ Commands invoked with a full path (e.g. `/usr/bin/rm`) are resolved to their bas
|
|
|
368
368
|
|
|
369
369
|
The first line `# $schema: ../../../schemas/command.schema.json` is a convention for IDE support. It is not parsed by bash-classify itself but provides autocomplete and validation when editing YAML files in editors that support JSON Schema.
|
|
370
370
|
|
|
371
|
-
## 8.
|
|
371
|
+
## 8. Risk Levels
|
|
372
|
+
|
|
373
|
+
Each command also has a risk level (`LOW`, `MEDIUM`, `HIGH`) that defaults based on classification. You only need to set `risk` explicitly in YAML when the default does not fit.
|
|
374
|
+
|
|
375
|
+
### When to set `risk: LOW`
|
|
376
|
+
|
|
377
|
+
Use for safe routine operations that should be auto-allowed, even though their classification is above READONLY:
|
|
378
|
+
|
|
379
|
+
```yaml
|
|
380
|
+
# git add only stages files -- safe to auto-allow
|
|
381
|
+
subcommands:
|
|
382
|
+
add:
|
|
383
|
+
classification: LOCAL_EFFECTS
|
|
384
|
+
risk: LOW
|
|
385
|
+
```
|
|
386
|
+
|
|
387
|
+
Other good candidates: `git fetch`, `mkdir`, `touch`, code formatters like `ruff format`, `prettier`.
|
|
388
|
+
|
|
389
|
+
### When to leave the default (`MEDIUM`)
|
|
390
|
+
|
|
391
|
+
The default `MEDIUM` is appropriate for most `LOCAL_EFFECTS` and `EXTERNAL_EFFECTS` commands. If the command does what its classification says and nothing surprising, don't set `risk` at all.
|
|
392
|
+
|
|
393
|
+
### When to set `risk: HIGH`
|
|
394
|
+
|
|
395
|
+
Use when a command is more dangerous than its classification default suggests -- e.g. an `EXTERNAL_EFFECTS` command that is particularly destructive or hard to reverse.
|
|
396
|
+
|
|
397
|
+
### `DANGEROUS` and `UNKNOWN` are always `HIGH`
|
|
398
|
+
|
|
399
|
+
Commands classified as `DANGEROUS` or `UNKNOWN` are automatically clamped to `HIGH` risk regardless of any explicit `risk` field. You never need to set `risk` on these.
|
|
400
|
+
|
|
401
|
+
### Risk on options
|
|
402
|
+
|
|
403
|
+
Options can override risk the same way they override classification:
|
|
404
|
+
|
|
405
|
+
```yaml
|
|
406
|
+
subcommands:
|
|
407
|
+
apply:
|
|
408
|
+
classification: EXTERNAL_EFFECTS
|
|
409
|
+
options:
|
|
410
|
+
--dry-run: {takes_value: true, overrides: READONLY, risk: LOW}
|
|
411
|
+
```
|
|
412
|
+
|
|
413
|
+
## 9. Common Patterns
|
|
372
414
|
|
|
373
415
|
| Pattern | Example | Classification |
|
|
374
416
|
|---------|---------|---------------|
|
|
@@ -18,6 +18,10 @@
|
|
|
18
18
|
"classification": {
|
|
19
19
|
"$ref": "#/$defs/Classification"
|
|
20
20
|
},
|
|
21
|
+
"risk": {
|
|
22
|
+
"$ref": "#/$defs/Risk",
|
|
23
|
+
"description": "Explicit risk level override for this command (default derived from classification)"
|
|
24
|
+
},
|
|
21
25
|
"strict": {
|
|
22
26
|
"type": "boolean",
|
|
23
27
|
"description": "If true (default), unrecognized options yield UNKNOWN"
|
|
@@ -44,6 +48,11 @@
|
|
|
44
48
|
"enum": ["READONLY", "LOCAL_EFFECTS", "EXTERNAL_EFFECTS", "DANGEROUS", "UNKNOWN"],
|
|
45
49
|
"description": "Classification level for a command or option override"
|
|
46
50
|
},
|
|
51
|
+
"Risk": {
|
|
52
|
+
"type": "string",
|
|
53
|
+
"enum": ["LOW", "MEDIUM", "HIGH"],
|
|
54
|
+
"description": "Risk level for a command or option override"
|
|
55
|
+
},
|
|
47
56
|
"DelegationConfig": {
|
|
48
57
|
"type": "object",
|
|
49
58
|
"required": ["mode"],
|
|
@@ -95,6 +104,10 @@
|
|
|
95
104
|
"$ref": "#/$defs/Classification",
|
|
96
105
|
"description": "When this option is present, override the classification to this level"
|
|
97
106
|
},
|
|
107
|
+
"risk": {
|
|
108
|
+
"$ref": "#/$defs/Risk",
|
|
109
|
+
"description": "When this option is present, override the risk level"
|
|
110
|
+
},
|
|
98
111
|
"captures_directory": {
|
|
99
112
|
"type": "boolean",
|
|
100
113
|
"description": "The value of this option is a working directory"
|
|
@@ -118,6 +131,10 @@
|
|
|
118
131
|
"classification": {
|
|
119
132
|
"$ref": "#/$defs/Classification"
|
|
120
133
|
},
|
|
134
|
+
"risk": {
|
|
135
|
+
"$ref": "#/$defs/Risk",
|
|
136
|
+
"description": "Explicit risk level override for this subcommand (default derived from classification)"
|
|
137
|
+
},
|
|
121
138
|
"strict": {
|
|
122
139
|
"type": "boolean",
|
|
123
140
|
"description": "If true (default), unrecognized options yield UNKNOWN"
|
|
@@ -2,13 +2,14 @@
|
|
|
2
2
|
|
|
3
3
|
from bash_classify.classifier import classify_expression
|
|
4
4
|
from bash_classify.database import CommandDatabase, load_database
|
|
5
|
-
from bash_classify.models import Classification, CommandResult, ExpressionResult
|
|
5
|
+
from bash_classify.models import Classification, CommandResult, ExpressionResult, Risk
|
|
6
6
|
|
|
7
7
|
__all__ = [
|
|
8
8
|
"classify_expression",
|
|
9
9
|
"load_database",
|
|
10
10
|
"CommandDatabase",
|
|
11
11
|
"Classification",
|
|
12
|
+
"Risk",
|
|
12
13
|
"ExpressionResult",
|
|
13
14
|
"CommandResult",
|
|
14
15
|
]
|
|
@@ -14,6 +14,7 @@ from .models import (
|
|
|
14
14
|
ExpressionResult,
|
|
15
15
|
InnerCommandResult,
|
|
16
16
|
Redirect,
|
|
17
|
+
Risk,
|
|
17
18
|
)
|
|
18
19
|
from .parser import parse_expression
|
|
19
20
|
|
|
@@ -94,6 +95,7 @@ def classify_expression(
|
|
|
94
95
|
command=[invocation.argv[0]],
|
|
95
96
|
argv=list(invocation.argv),
|
|
96
97
|
classification=Classification.DANGEROUS,
|
|
98
|
+
risk=Risk.HIGH,
|
|
97
99
|
matched_rule=None,
|
|
98
100
|
inner_commands=[],
|
|
99
101
|
classification_reason="variable expansion in command position",
|
|
@@ -112,12 +114,15 @@ def classify_expression(
|
|
|
112
114
|
if result.classification_reason
|
|
113
115
|
else "elevated by output redirect"
|
|
114
116
|
)
|
|
117
|
+
# Elevate risk to at least MEDIUM for output redirects
|
|
118
|
+
result.risk = Risk.max_severity(result.risk, Risk.MEDIUM)
|
|
115
119
|
# /dev/tcp and /dev/udp redirects are network access -> DANGEROUS
|
|
116
120
|
if redirect.target.startswith("/dev/tcp/") or redirect.target.startswith("/dev/udp/"):
|
|
117
121
|
elevated = Classification.max_severity(result.classification, Classification.DANGEROUS)
|
|
118
122
|
if elevated != result.classification:
|
|
119
123
|
result.classification = elevated
|
|
120
124
|
result.classification_reason = "elevated to DANGEROUS: /dev/tcp or /dev/udp access detected"
|
|
125
|
+
result.risk = Risk.HIGH
|
|
121
126
|
|
|
122
127
|
# Step 4b: Check for /dev/tcp and /dev/udp in command arguments
|
|
123
128
|
for arg in invocation.argv:
|
|
@@ -126,6 +131,7 @@ def classify_expression(
|
|
|
126
131
|
if elevated != result.classification:
|
|
127
132
|
result.classification = elevated
|
|
128
133
|
result.classification_reason = "elevated to DANGEROUS: /dev/tcp or /dev/udp access detected"
|
|
134
|
+
result.risk = Risk.HIGH
|
|
129
135
|
|
|
130
136
|
# Step 5: Apply backgrounding
|
|
131
137
|
if invocation.is_background:
|
|
@@ -137,6 +143,8 @@ def classify_expression(
|
|
|
137
143
|
if result.classification_reason
|
|
138
144
|
else "elevated by backgrounding"
|
|
139
145
|
)
|
|
146
|
+
# Elevate risk to at least MEDIUM for backgrounding
|
|
147
|
+
result.risk = Risk.max_severity(result.risk, Risk.MEDIUM)
|
|
140
148
|
|
|
141
149
|
# Step 6: Elevate to DANGEROUS when writing to system directories
|
|
142
150
|
if result.classification.severity() >= Classification.LOCAL_EFFECTS.severity():
|
|
@@ -155,6 +163,7 @@ def classify_expression(
|
|
|
155
163
|
result.classification_reason = (
|
|
156
164
|
result.classification_reason or ""
|
|
157
165
|
) + f"; elevated to DANGEROUS: system path {system_paths_found[0]}"
|
|
166
|
+
result.risk = Risk.HIGH
|
|
158
167
|
|
|
159
168
|
command_results.append(result)
|
|
160
169
|
all_redirects.extend(invocation.redirects)
|
|
@@ -162,17 +171,21 @@ def classify_expression(
|
|
|
162
171
|
# Step 7: Collect directories
|
|
163
172
|
directories = _collect_directories(command_results)
|
|
164
173
|
|
|
165
|
-
# Step 8: Compute composite classification
|
|
174
|
+
# Step 8: Compute composite classification and risk
|
|
166
175
|
if not command_results and parse_warnings:
|
|
167
176
|
overall = Classification.UNKNOWN
|
|
177
|
+
overall_risk = Risk.HIGH
|
|
168
178
|
elif command_results:
|
|
169
179
|
overall = Classification.max_severity(*(r.classification for r in command_results))
|
|
180
|
+
overall_risk = Risk.max_severity(*(r.risk for r in command_results))
|
|
170
181
|
else:
|
|
171
182
|
overall = Classification.READONLY # empty input
|
|
183
|
+
overall_risk = Risk.LOW
|
|
172
184
|
|
|
173
185
|
return ExpressionResult(
|
|
174
186
|
expression=expression,
|
|
175
187
|
classification=overall,
|
|
188
|
+
risk=overall_risk,
|
|
176
189
|
directories=directories,
|
|
177
190
|
commands=command_results,
|
|
178
191
|
redirects=all_redirects,
|
|
@@ -22,6 +22,7 @@ def _inner_command_to_dict(result: InnerCommandResult) -> dict:
|
|
|
22
22
|
"command": result.command,
|
|
23
23
|
"argv": result.argv,
|
|
24
24
|
"classification": result.classification.value,
|
|
25
|
+
"risk": result.risk.value,
|
|
25
26
|
"matched_rule": result.matched_rule,
|
|
26
27
|
}
|
|
27
28
|
|
|
@@ -43,6 +44,7 @@ def _command_to_dict(result: CommandResult) -> dict:
|
|
|
43
44
|
"command": result.command,
|
|
44
45
|
"argv": result.argv,
|
|
45
46
|
"classification": result.classification.value,
|
|
47
|
+
"risk": result.risk.value,
|
|
46
48
|
"matched_rule": result.matched_rule,
|
|
47
49
|
}
|
|
48
50
|
|
|
@@ -74,6 +76,7 @@ def _result_to_dict(result: ExpressionResult) -> dict:
|
|
|
74
76
|
d: dict = {
|
|
75
77
|
"expression": result.expression,
|
|
76
78
|
"classification": result.classification.value,
|
|
79
|
+
"risk": result.risk.value,
|
|
77
80
|
"directories": result.directories,
|
|
78
81
|
"commands": [_command_to_dict(cmd) for cmd in result.commands],
|
|
79
82
|
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# $schema: ../../../schemas/command.schema.json
|
|
2
|
+
command: agent-browser
|
|
3
|
+
description: "Fast browser automation CLI for AI agents"
|
|
4
|
+
classification: EXTERNAL_EFFECTS
|
|
5
|
+
strict: false
|
|
6
|
+
global_options:
|
|
7
|
+
--help: {overrides: READONLY}
|
|
8
|
+
--version: {overrides: READONLY}
|
|
9
|
+
-V: {overrides: READONLY}
|
|
@@ -13,14 +13,18 @@ subcommands:
|
|
|
13
13
|
classification: READONLY
|
|
14
14
|
install:
|
|
15
15
|
classification: LOCAL_EFFECTS
|
|
16
|
+
risk: LOW
|
|
16
17
|
uninstall:
|
|
17
18
|
classification: LOCAL_EFFECTS
|
|
19
|
+
risk: LOW
|
|
18
20
|
update:
|
|
19
21
|
classification: LOCAL_EFFECTS
|
|
22
|
+
risk: LOW
|
|
20
23
|
upgrade:
|
|
21
24
|
classification: LOCAL_EFFECTS
|
|
22
25
|
cleanup:
|
|
23
26
|
classification: LOCAL_EFFECTS
|
|
27
|
+
risk: LOW
|
|
24
28
|
doctor:
|
|
25
29
|
classification: READONLY
|
|
26
30
|
config:
|
|
@@ -7,8 +7,10 @@ global_options:
|
|
|
7
7
|
subcommands:
|
|
8
8
|
build:
|
|
9
9
|
classification: LOCAL_EFFECTS
|
|
10
|
+
risk: LOW
|
|
10
11
|
test:
|
|
11
12
|
classification: LOCAL_EFFECTS
|
|
13
|
+
risk: LOW
|
|
12
14
|
run:
|
|
13
15
|
classification: DANGEROUS
|
|
14
16
|
check:
|
|
@@ -19,18 +21,23 @@ subcommands:
|
|
|
19
21
|
--fix: {overrides: LOCAL_EFFECTS}
|
|
20
22
|
fmt:
|
|
21
23
|
classification: LOCAL_EFFECTS
|
|
24
|
+
risk: LOW
|
|
22
25
|
doc:
|
|
23
26
|
classification: LOCAL_EFFECTS
|
|
27
|
+
risk: LOW
|
|
24
28
|
publish:
|
|
25
29
|
classification: DANGEROUS
|
|
26
30
|
install:
|
|
27
31
|
classification: LOCAL_EFFECTS
|
|
32
|
+
risk: LOW
|
|
28
33
|
options:
|
|
29
34
|
--list: {overrides: READONLY}
|
|
30
35
|
clean:
|
|
31
36
|
classification: LOCAL_EFFECTS
|
|
37
|
+
risk: LOW
|
|
32
38
|
update:
|
|
33
39
|
classification: LOCAL_EFFECTS
|
|
40
|
+
risk: LOW
|
|
34
41
|
search:
|
|
35
42
|
classification: READONLY
|
|
36
43
|
tree:
|
|
@@ -41,15 +48,22 @@ subcommands:
|
|
|
41
48
|
classification: READONLY
|
|
42
49
|
bench:
|
|
43
50
|
classification: LOCAL_EFFECTS
|
|
51
|
+
risk: LOW
|
|
44
52
|
init:
|
|
45
53
|
classification: LOCAL_EFFECTS
|
|
54
|
+
risk: LOW
|
|
46
55
|
new:
|
|
47
56
|
classification: LOCAL_EFFECTS
|
|
57
|
+
risk: LOW
|
|
48
58
|
fix:
|
|
49
59
|
classification: LOCAL_EFFECTS
|
|
60
|
+
risk: LOW
|
|
50
61
|
add:
|
|
51
62
|
classification: LOCAL_EFFECTS
|
|
63
|
+
risk: LOW
|
|
52
64
|
remove:
|
|
53
65
|
classification: LOCAL_EFFECTS
|
|
66
|
+
risk: LOW
|
|
54
67
|
generate-lockfile:
|
|
55
68
|
classification: LOCAL_EFFECTS
|
|
69
|
+
risk: LOW
|
|
@@ -60,9 +60,11 @@ subcommands:
|
|
|
60
60
|
strict: false
|
|
61
61
|
build:
|
|
62
62
|
classification: LOCAL_EFFECTS
|
|
63
|
+
risk: LOW
|
|
63
64
|
strict: false
|
|
64
65
|
pull:
|
|
65
66
|
classification: LOCAL_EFFECTS
|
|
67
|
+
risk: LOW
|
|
66
68
|
strict: false
|
|
67
69
|
push:
|
|
68
70
|
classification: EXTERNAL_EFFECTS
|
|
@@ -114,9 +116,11 @@ subcommands:
|
|
|
114
116
|
strict: false
|
|
115
117
|
build:
|
|
116
118
|
classification: LOCAL_EFFECTS
|
|
119
|
+
risk: LOW
|
|
117
120
|
strict: false
|
|
118
121
|
pull:
|
|
119
122
|
classification: LOCAL_EFFECTS
|
|
123
|
+
risk: LOW
|
|
120
124
|
push:
|
|
121
125
|
classification: EXTERNAL_EFFECTS
|
|
122
126
|
exec:
|