🧹 Want your code to be clean every single time you hit commit?
Tired of manually fixing linting errors or arguing over code style in PRs?
This setup is for you.
🤔 Why Use This Setup?
Whether you’re working alone or in a team, this setup helps you:
- ✅ Keep your code clean and consistent automatically
 - ✅ Enforce formatting rules without remembering to run anything
 - ✅ Avoid polluting 
.gitignorewith local files like VS Code settings - ✅ Stay productive without annoying formatting distractions
 
📌 Use Cases:
You're contributing to a legacy or open-source codebase that doesn’t enforce linting yet — but you still want to follow high-quality standards just for your own changes.
You're part of a team, and not everyone uses the same dev tools. This lets you quietly enforce clean code locally without adding noise to the repo.
You're learning or mentoring, and want a low-effort way to keep Python code consistent and readable.
🛠️ Part 1: Install Required Tools
# Install these in your virtual environment
pip install ruff pre-commit
Why: These tools format your code and enforce coding standards automatically.
⚙️ Part 2: Create Project Configuration Files
✅ Step 1: Create Pre-commit Configuration
touch .pre-commit-config.yaml
Paste this into .pre-commit-config.yaml:
exclude: '(^|/)(alembic|tests)/|(^|/)__init__\.py$'
repos:
- repo: https://github.com/astral-sh/ruff-pre-commit
  rev: v0.9.10
  hooks:
    - id: ruff
      args: [ --fix ]
      stages: [pre-commit]
    - id: ruff-format
      stages: [pre-commit]
✅ Step 2: Configure Ruff Rules
touch pyproject.toml
Paste this into pyproject.toml:
[tool.ruff]
line-length = 88
target-version = "py311"
[tool.ruff.lint]
select = [
    "E",   # pycodestyle errors
    "F",   # pyflakes
    "I",   # isort
    "B",   # flake8-bugbear
]
ignore = ["D203", "D212"]
[tool.ruff.format]
quote-style = "double"
indent-style = "space"
[tool.ruff.lint.pydocstyle]
convention = "google"
  
  
  🚫 Part 3: Exclude Files Locally (Without .gitignore)
To keep your repository clean, we’ll exclude helper scripts and editor settings without adding them to .gitignore.
# This keeps files ignored only on your machine
echo "pyproject.toml" >> .git/info/exclude
echo ".vscode/settings.json" >> .git/info/exclude
Why: These files are personal and environment-specific. You need them — your team doesn’t.
💻 Part 4: Configure VS Code
mkdir -p .vscode
touch .vscode/settings.json
Paste this into .vscode/settings.json:
{
  "editor.formatOnSave": true,
  "editor.codeActionsOnSave": {
    "source.fixAll.ruff": "always",
    "source.organizeImports.ruff": "always"
  },
  "[python]": {
    "editor.defaultFormatter": "charliermarsh.ruff",
    "editor.formatOnSave": true
  },
  "ruff.format.preview": true,
  "autoDocstring.docstringFormat": "google",
  "autoDocstring.generateDocstringOnEnter": true
}
🔑 Part 5: Activate Pre-commit
# This creates a Git hook that makes pre-commit run automatically on every commit.  
pre-commit install
✅ Confirmed: Automatic Formatting on Commit
Here’s how your workflow looks after setup:
- You edit your code
 - You run 
git add . - You commit:
 
   git commit -m "Your message"
Then pre-commit:
- Runs Ruff to check and fix your code
 - If Ruff makes changes, the commit pauses
 - You’ll need to 
git addthe fixed files again - Then re-run 
git commit 
  
  
  🧪 Bonus: Run Ruff Only on Your Changes with check_my_changes.sh
This helper script is a must-have when:
- You're working on a large codebase
 - Ruff isn’t configured globally
 - You only want to lint and fix your own feature branch changes
 
  
  
  📄 check_my_changes.sh
#!/bin/bash
cd "$(git rev-parse --show-toplevel)"
echo "Getting changed Python files compared to dev branch..."
MODIFIED_FILES=$(git diff --name-only origin/dev...HEAD | grep '\.py$')
if [ -z "$MODIFIED_FILES" ]; then
    echo "No Python files changed in your branch."
    exit 0
fi
echo "============================================="
echo "Checking these files:"
echo "$MODIFIED_FILES"
echo "============================================="
echo "$MODIFIED_FILES" | xargs ruff check --fix
echo "============================================="
echo "Done! Your code is now cleaner."
echo "============================================="
💡 Use Case:
If the main repo doesn’t enforce linting yet (no Ruff config, no CI hooks), but you want your code to stay clean — this script lints only what you’ve touched, without you needing to run Ruff manually file by file.
🎯 Final Thoughts: Start Clean, Stay Clean
Code quality is not just for big teams or fancy open-source projects.
It starts with you.
Whether you're:
- Working solo
 - Contributing to a chaotic legacy repo
 - Just learning to write better Python
 - Or collaborating in a fast-paced team...
 
This setup gives you a head start — without needing permission, without needing a fancy CI setup, and without adding clutter to your repo.
Let Ruff and Pre-commit do the heavy lifting, so you can focus on building features — not fixing quotes and spacing.
✨ Bonus: When your team sees how clean your PRs are, they might adopt this too. Be the change 😎
🗣️ Over to You:
Try this out and tell me how it worked! Got questions? Found a tweak that improved your workflow? Drop a comment — I’d love to learn from you too.
    
Top comments (0)