Skip to main content

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 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.

Designed primarily as a Claude Code hook to automatically allow low-risk 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 plugin

The repo includes a Claude Code plugin that auto-allows low-risk bash commands via a PreToolUse hook.

# Install the bash-classify CLI
uv tool install bash-classify

# Add the marketplace and install the plugin
claude plugin marketplace add fprochazka/bash-classify
claude plugin install bash-classify-hook@fprochazka-bash-classify

To upgrade after a new release:

uv tool install --force bash-classify
claude plugin marketplace update fprochazka-bash-classify
claude plugin update bash-classify-hook@fprochazka-bash-classify

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.

Command database

The classification database includes 120+ command definitions covering common Unix utilities, package managers, container tools, cloud CLIs, and more.

Classification levels

Level Description Examples
READONLY No side effects ls, cat, grep, kubectl get
LOCAL_EFFECTS Modifies local files or state only git add, git commit, cp, mkdir, pytest
EXTERNAL_EFFECTS Interacts with external systems git push, kubectl apply, curl -d
DANGEROUS Destructive, system-wide, or irreversible rm -rf, git push --force, chmod
UNKNOWN Command not in database Any unrecognized command

Risk levels

Each command also gets a risk rating, orthogonal to classification:

Risk Description Examples
LOW Safe, routine operation — auto-approved ls, git add, git commit, mkdir, ruff format
MEDIUM Normal caution warranted git push, cp, npm run, git rebase
HIGH Dangerous or unknown — always requires confirmation rm -rf, git push --force, unknown commands

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.

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 get and kubectl delete can have different classifications
  • Delegation for wrappers -- commands like xargs, sudo, and env delegate classification to the inner command

Python API

from bash_classify import classify_expression

result = classify_expression("kubectl get pods")
print(result.classification)  # Classification.READONLY
print(result.risk)            # Risk.LOW

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.

Releasing

Version is derived automatically from git tags via hatch-vcs — no manual version bumping needed.

Before tagging, bump the version in both plugin manifest files:

  • coding-agent-plugins/claude-code/.claude-plugin/plugin.json
  • .claude-plugin/marketplace.json

Wait for CI to pass on master, then tag, push, and create a GitHub release:

# Review changes since last release
git log $(git describe --tags --abbrev=0)..HEAD --oneline

git tag v<version>
git push origin v<version>
gh release create v<version> --title "v<version>" --notes "..."

The publish.yml GitHub Action builds and publishes to PyPI automatically via trusted publishing.

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

bash_classify-0.3.0.tar.gz (101.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

bash_classify-0.3.0-py3-none-any.whl (88.6 kB view details)

Uploaded Python 3

File details

Details for the file bash_classify-0.3.0.tar.gz.

File metadata

  • Download URL: bash_classify-0.3.0.tar.gz
  • Upload date:
  • Size: 101.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for bash_classify-0.3.0.tar.gz
Algorithm Hash digest
SHA256 9213d372f475028abb8d0b64130ecdeefbd93059884b2a9ce4f9a58c42882b63
MD5 c93e7677a5e6c9e1b3f239239f3955a7
BLAKE2b-256 6f55800aabbfd0253bd467352acc61beed0cede8c0bfdd4afac47ec07f82603b

See more details on using hashes here.

Provenance

The following attestation bundles were made for bash_classify-0.3.0.tar.gz:

Publisher: publish.yml on fprochazka/bash-classify

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file bash_classify-0.3.0-py3-none-any.whl.

File metadata

  • Download URL: bash_classify-0.3.0-py3-none-any.whl
  • Upload date:
  • Size: 88.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for bash_classify-0.3.0-py3-none-any.whl
Algorithm Hash digest
SHA256 8734445b9eac43d87adea0d9896d92f677fe568abfe64fcfefe049e46b76894f
MD5 f894ecabb14c4da5ae4b5bae834c3000
BLAKE2b-256 6bb3475394a1cb003aa6d63f9b67e42152f7f9e76456b0f37ac3178c1e4793ed

See more details on using hashes here.

Provenance

The following attestation bundles were made for bash_classify-0.3.0-py3-none-any.whl:

Publisher: publish.yml on fprochazka/bash-classify

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page