A safety-first Python scanner and GitHub App workflow for reviewable, AI-assisted refactoring.
Deterministic AST analysis first. Optional LLM proposals second. Human approval always.
Use it as a local CLI for an immediate scan, as a Docker-based GitHub Action for a CI quality gate, or as a signed-webhook GitHub App service for pull-request annotations. Each path uses the same deterministic analyzer and typed findings.
The public demo runs the repository's real deterministic PythonScanner behind
a small FastAPI endpoint. Paste a Python snippet and it returns rule IDs,
locations, severity, OWASP context and remediation without importing or
executing the submitted code. It does not call an LLM and the application does
not persist the snippet.
Launch the scanner or inspect its interactive OpenAPI documentation. The hosted surface is deliberately narrower than the installable GitHub App: webhooks, repository writes and model calls still require a local or privately configured deployment.
This project started as a private tool for experimenting with automated code review and refactoring workflows. The original workflow eventually moved on and the repository was no longer needed in its private home. Instead of letting it disappear in an archive, I removed the private assumptions, tightened the safety boundaries, documented the system and published it in case someone else finds a use for it.
It is intentionally not an autonomous “rewrite my repository” bot. The useful part is the controlled pipeline around analysis: source code is parsed without being executed, findings are reproducible, generated changes remain proposals, and repository writes require an explicitly reviewed content hash.
- Scan Python files through the standard-library AST without importing target code.
- Detect a focused set of high-signal security and maintenance patterns.
- Produce human-readable output or stable JSON for CI integrations.
- Limit pull-request annotations to lines that actually changed.
- Verify GitHub webhook signatures and deduplicate delivery IDs.
- Publish a Check Run conclusion through a replaceable GitHub client port.
- Generate deterministic offline remediation, test and changelog proposals.
- Optionally route proposals through any LiteLLM-compatible model.
- Apply one approved file on a new branch after verifying its SHA-256 digest.
- Run as a CLI, Docker container, Docker-based GitHub Action or FastAPI service.
git clone https://github.com/General-Iroh32/ai-code-refactor-agent.git
cd ai-code-refactor-agent
python -m venv .venv
source .venv/bin/activate
python -m pip install -e '.[api,dev]'
refactor-agent analyze ./src --fail-on high
pytestThe command exits with status 1 when a finding reaches the configured
threshold, which makes the scanner usable as a CI quality gate. Use
--format json when another tool should consume the result.
Example output:
Scanned 1 Python file(s) under /work/example
CRITICAL RA101 service.py:8:11 Dynamic code execution
HIGH RA102 service.py:14:4 Shell command execution enabled
HIGH RA107 settings.py:4:0 Probable hard-coded credential
flowchart LR
Source[Python source or PR diff] --> Scanner[Deterministic AST scanner]
Scanner --> Findings[Typed findings + severity]
Findings --> Gate{Quality gate}
Gate -->|local / CI| Report[Text or JSON report]
Gate -->|GitHub App| Check[Check Run annotations]
Findings --> Provider[Refactor provider port]
Provider --> Offline[Offline proposals]
Provider --> LLM[Optional LiteLLM provider]
Offline --> Review[Isolated review artifacts]
LLM --> Review
Review --> Hash[SHA-256 approval check]
Hash --> Branch[New refactor-agent/* branch]
The scanner, orchestration service, Git adapter, GitHub client and model provider are separate ports. Tests replace network boundaries with deterministic recording adapters, so the important behavior is testable without credentials.
| Rule | Detects | Severity | Review context |
|---|---|---|---|
RA000 |
Python syntax that cannot be parsed | high | Broken or incomplete source |
RA101 |
eval and exec |
critical | Injection |
RA102 |
shell=True and os.system |
high | Command injection |
RA103 |
Unsafe YAML loading | high | Software/data integrity |
RA104 |
Pickle deserialization | high | Unsafe deserialization |
RA105 |
MD5 and SHA-1 | medium | Cryptographic weakness |
RA106 |
Requests with verify=False |
high | Transport verification |
RA107 |
Probable hard-coded credentials | high | Secret exposure |
Import aliases and direct imports are resolved for supported calls. Virtual environments, build output and common tool caches are excluded from directory scans. The rules are review heuristics—not vulnerability verdicts—and their limits are documented in the security model.
name: Security scan
on: [push, pull_request]
permissions:
contents: read
jobs:
refactor-agent:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
with:
persist-credentials: false
- uses: General-Iroh32/ai-code-refactor-agent@v0.1.0
with:
path: src
fail-on: high
format: textThe Docker action runs the same scanner as the local CLI. Pin the release tag or a full commit SHA when the workflow requires an immutable dependency.
export REFACTOR_AGENT_WEBHOOK_SECRET='replace-with-a-random-secret'
export REFACTOR_AGENT_DRY_RUN=true
uvicorn refactor_agent.api:create_app \
--factory \
--host 127.0.0.1 \
--port 8000Open http://localhost:8000/docs and send GitHub events to
POST /webhooks/github. The service:
- verifies
X-Hub-Signature-256against the raw request body; - claims and deduplicates
X-GitHub-Delivery; - accepts supported
pull_requestactions; - scans changed Python lines in the PR diff;
- maps findings to Check Run annotations;
- returns success, warning or failure from the configured threshold.
Dry-run mode uses RecordingGitHubClient and makes no GitHub writes. Live mode
expects a short-lived installation token from the caller's secret layer. The
required permissions and example manifest live in
GitHub App setup.
The default provider is deliberately offline and deterministic:
refactor-agent plan ./src --artifacts .refactor-agent/reviewTo request proposals from a hosted model:
python -m pip install -e '.[llm]'
refactor-agent plan ./src \
--provider litellm \
--model provider/model \
--artifacts .refactor-agent/reviewModel output is marked as generated, stored outside the source tree and never executed or committed automatically. Reviewers remain responsible for provider data handling and every proposed change.
RepositoryService.apply_approved_change proceeds only when all checks pass:
- the working tree is clean;
- the target is an existing repository-relative file;
- the proposed content matches the exact reviewed SHA-256 digest;
- the destination is a new
refactor-agent/*branch; - the commit message is non-empty.
Stale content and direct writes to main, master, develop or release are
rejected. Opening or merging a pull request stays outside the service so normal
repository policy remains authoritative.
cp .env.example .env
docker compose up --build
curl http://127.0.0.1:8000/healthzThe runtime uses a non-root user. Compose binds to loopback, drops Linux
capabilities, enables no-new-privileges, mounts a read-only root filesystem and
starts in dry-run mode. Tagged releases publish an attested image to
ghcr.io/general-iroh32/ai-code-refactor-agent.
ruff format --check .
ruff check .
mypy src
pytest
python -m buildThe current suite contains 35 tests and enforces at least 85% coverage. CI runs the package on Python 3.11, 3.12 and 3.13, builds the distribution and exercises the public Docker action against the repository itself.
src/refactor_agent/
├── analyzer/ # AST scanner and supported rules
├── github_app/ # webhook, PR processor and GitHub adapters
├── git_service/ # reviewed branch/commit workflow
├── llm/ # offline and optional LiteLLM providers
├── api.py # FastAPI application factory
├── artifacts.py # isolated proposal writer
├── cli.py # Typer commands
├── config.py # validated environment configuration
├── models.py # stable domain records
└── service.py # analysis/refactor orchestration
- The scanner intentionally favors a small explainable rule set over broad SAST coverage.
- Python AST analysis cannot prove runtime exploitability or detect every data flow.
- Delivery deduplication is process-local; horizontally scaled deployments need a shared store.
- The GitHub App adapter accepts an installation token but does not implement the JWT exchange itself.
- AI proposals require human review and are never treated as trusted code.
Released under the MIT License. Use it, adapt it, or take only the pieces that are useful to you.
