Classify bash commands as READONLY, WRITE, DANGEROUS, or UNKNOWN
Project description
bash-classify
Classify bash commands by their side-effect risk level.
What it does
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 into four levels: READONLY, WRITE, DANGEROUS, and UNKNOWN.
Designed primarily as a Claude Code hook to automatically allow safe, read-only commands while flagging risky ones for human review.
Installation
uv tool install bash-classify
# or
pip install bash-classify
Quick start
$ echo 'kubectl get pods -n production' | bash-classify | jq '.classification'
"READONLY"
$ echo 'git push --force origin main' | bash-classify | jq '.classification'
"DANGEROUS"
$ echo 'cp file.txt /etc/config' | bash-classify | jq '.classification'
"DANGEROUS"
$ echo 'find . -name "*.pyc" -delete' | bash-classify | jq '.classification'
"DANGEROUS"
Claude Code hook
Install as a Claude Code hook to auto-allow read-only commands and require approval for everything else:
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [
{
"type": "command",
"command": "echo \"$CLAUDE_TOOL_INPUT\" | jq -r '.command' | bash-classify",
"timeout": 5000,
"on_output": [
{
"matcher": "\"classification\": \"READONLY\"",
"action": "approve"
}
]
}
]
}
]
}
}
Command database
The classification database includes 120+ command definitions covering common Unix utilities, package managers, container tools, cloud CLIs, and more.
- See docs/classification-guidance.md for how to add new commands
- YAML definitions are validated against a JSON Schema for IDE autocomplete and CI checks
Classification levels
| Level | Description | Examples |
|---|---|---|
READONLY |
No side effects, safe to auto-approve | ls, cat, grep, kubectl get |
WRITE |
Modifies local files or state | mkdir, cp, git commit |
DANGEROUS |
Destructive, system-wide, or irreversible | rm -rf, git push --force, chmod |
UNKNOWN |
Command not in database | Any unrecognized command |
How it works
- Tree-sitter parsing -- bash expressions are parsed into an AST for accurate command extraction, handling pipes, subshells, and command substitution
- YAML command database -- each command has classification rules with subcommand and option matching
- Subcommand matching --
kubectl getandkubectl deletecan have different classifications - Delegation for wrappers -- commands like
xargs,sudo, andenvdelegate classification to the inner command
Python API
from bash_classify import classify_expression
result = classify_expression("kubectl get pods")
print(result.classification) # Classification.READONLY
See SPEC.md for the full specification.
Development
git clone https://github.com/fprochazka/bash-classify.git
cd bash-classify
uv sync --dev
Run tests and linting before committing:
uv run ruff format .
uv run ruff check .
uv run pytest
To add or modify command definitions, see docs/classification-guidance.md. All YAML files in src/bash_classify/commands/ are validated against a JSON Schema — your IDE will provide autocomplete if it supports the # $schema: comment.
License
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file bash_classify-0.1.0.tar.gz.
File metadata
- Download URL: bash_classify-0.1.0.tar.gz
- Upload date:
- Size: 89.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2c0dce27f2090752830397a1ac5551014f3e37679014b48b682f4f8273ac618e
|
|
| MD5 |
ea79a6575fe0515f16041dbb24b8197c
|
|
| BLAKE2b-256 |
446f1765599f2bcb2f621dad75b85e3b847c31e3d69a324998e6c3533bcca8a6
|
Provenance
The following attestation bundles were made for bash_classify-0.1.0.tar.gz:
Publisher:
publish.yml on fprochazka/bash-classify
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
bash_classify-0.1.0.tar.gz -
Subject digest:
2c0dce27f2090752830397a1ac5551014f3e37679014b48b682f4f8273ac618e - Sigstore transparency entry: 1180357674
- Sigstore integration time:
-
Permalink:
fprochazka/bash-classify@f051fe23ac371f309ffacb47a520c1d36e9c73a8 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/fprochazka
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@f051fe23ac371f309ffacb47a520c1d36e9c73a8 -
Trigger Event:
push
-
Statement type:
File details
Details for the file bash_classify-0.1.0-py3-none-any.whl.
File metadata
- Download URL: bash_classify-0.1.0-py3-none-any.whl
- Upload date:
- Size: 66.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e0b272dcc5413c66ea299aa36280aded27bbf5864cfdad14cd8f9fa77d65faea
|
|
| MD5 |
7ce26ea4b5f6739544e0974ea698fb46
|
|
| BLAKE2b-256 |
240b3171b312f6f262580529dbe9dc2876ce708094f4ef4ace1bf3d0259d1b5f
|
Provenance
The following attestation bundles were made for bash_classify-0.1.0-py3-none-any.whl:
Publisher:
publish.yml on fprochazka/bash-classify
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
bash_classify-0.1.0-py3-none-any.whl -
Subject digest:
e0b272dcc5413c66ea299aa36280aded27bbf5864cfdad14cd8f9fa77d65faea - Sigstore transparency entry: 1180357701
- Sigstore integration time:
-
Permalink:
fprochazka/bash-classify@f051fe23ac371f309ffacb47a520c1d36e9c73a8 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/fprochazka
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@f051fe23ac371f309ffacb47a520c1d36e9c73a8 -
Trigger Event:
push
-
Statement type: