curl -fsSL https://raw.githubusercontent.com/robinojw/llm-bouncer/main/scripts/install.sh | bashA language-agnostic code quality gate for AI coding agents. Hooks into Claude Code and Codex CLI to catch style violations before they land, forcing the agent to fix its own output.
| Language | File extensions | Naming convention |
|---|---|---|
| Go | .go |
snake_case.go |
| Python | .py |
snake_case.py |
| TypeScript | .ts, .tsx |
camelCase.ts, PascalCase.tsx, kebab-case.ts |
| JavaScript | .js, .jsx |
camelCase.js, PascalCase.jsx, kebab-case.js |
| Rust | .rs |
snake_case.rs |
| Java | .java |
PascalCase.java |
| Kotlin | .kt, .kts |
PascalCase.kt, camelCase.kt |
| Swift | .swift |
PascalCase.swift, Type+Extension.swift |
Powered by tree-sitter for universal AST parsing.
When Claude Code writes or edits a supported file, the PostToolUse hook pipes the event to the llm-bouncer binary. If violations are found, it returns {"decision": "block", "reason": "..."} and Claude must fix the issues before continuing.
For Codex CLI (which lacks native hook support), a wrapper script diffs changed files after each run.
| Rule | What it catches | Language notes |
|---|---|---|
naming |
Single-letter variables (except i, j, k, _) |
Python also allows self, cls; Go excludes method receivers |
no-nested-ifs |
if inside if — use early returns or extract a helper |
Rust uses if_expression |
no-inline-booleans |
&&/||/and/or directly in if conditions |
Python uses and/or keywords |
no-inline-comments |
Comments on the same line as code | All comment syntaxes: //, #, /* */ |
no-repeated-strings |
Same string literal used more than once | Includes template strings for JS/TS |
no-magic-numbers |
Numeric literals (except 0 and 1) outside constants |
Go: const block, JS/TS: const keyword, Python: UPPER_SNAKE_CASE, Java: final, Kotlin: val, Swift: let |
cyclomatic-complexity |
Functions exceeding complexity threshold (default 10) | Counts if, loops, cases, &&/|| |
file-size |
Files exceeding line limit (default 300) | |
file-naming |
Filenames violating language convention | See table above |
curl -fsSL https://raw.githubusercontent.com/robinojw/llm-bouncer/main/scripts/install.sh | bashOr clone and run locally:
git clone https://github.com/robinojw/llm-bouncer.git
cd llm-bouncer
bash install.shThis builds the binary, installs it to ~/.llm-bouncer/bin/, and patches global configs for:
- Claude Code — adds a
PostToolUsehook to~/.claude/settings.json - Codex CLI — installs a wrapper script at
~/.llm-bouncer/codex-lint.sh
Requires: Go 1.21+, git, python3, and a C compiler (CGO is required for tree-sitter).
Codex CLI doesn't support PostToolUse hooks yet. Use the wrapper script:
~/.llm-bouncer/codex-lint.sh "add a new endpoint"See openai/codex#7396 for native hook support progress.
bash install.sh --uninstallRemoves the binary, wrapper, and all hook entries from global configs.
Run directly against any supported file:
./llm-bouncer path/to/file.py
./llm-bouncer path/to/component.tsxReturns JSON on stdout when violations are found, exits silently when clean.
The defaults are conservative. Adjust these constants in the source to match your codebase:
| Constant | File | Default | Description |
|---|---|---|---|
MaxFileLines |
checker/files.go |
300 | Maximum lines per file |
maxCyclomaticComplexity |
checker/complexity.go |
10 | Maximum cyclomatic complexity per function |
.
├── main.go # Hook entry point — reads stdin JSON or CLI args
├── language/
│ ├── language.go # LanguageConfig type, Detect(), registry
│ ├── go.go # Go config
│ ├── python.go # Python config
│ ├── typescript.go # TypeScript config
│ ├── javascript.go # JavaScript config
│ ├── rust.go # Rust config
│ ├── java.go # Java config
│ ├── kotlin.go # Kotlin config
│ └── swift.go # Swift config
├── checker/
│ ├── checker.go # Violation type, tree-sitter parsing, walk helpers
│ ├── complexity.go # Cyclomatic complexity check
│ ├── files.go # File size and naming checks
│ ├── naming.go # Variable and parameter naming checks
│ └── style.go # Nested ifs, inline booleans, comments, strings, magic numbers
├── docs/
│ └── plans/ # Implementation plans
├── install.sh # Global installer (build + config patching)
├── codex-lint.sh # Codex CLI wrapper script
└── go.mod
MIT