├── tests └── __init__.py ├── py_diffbro ├── __init__.py ├── modules │ ├── app_types.py │ ├── cmd.py │ ├── git.py │ ├── constants.py │ ├── llm.py │ └── bro.py └── main.py ├── .env.sample ├── scripts ├── run_tox.py ├── publish_pypi.py └── publish_testpypi.py ├── tox.ini ├── pyproject.toml ├── .gitignore └── README.md /tests/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /py_diffbro/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.env.sample: -------------------------------------------------------------------------------- 1 | OPENAI_API_KEY= -------------------------------------------------------------------------------- /py_diffbro/modules/app_types.py: -------------------------------------------------------------------------------- 1 | from enum import Enum 2 | 3 | 4 | class BroMode(str, Enum): 5 | CHILL = "chill" 6 | MID = "mid" 7 | CHAD = "chad" 8 | -------------------------------------------------------------------------------- /scripts/run_tox.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import subprocess 3 | 4 | 5 | def main(): 6 | subprocess.run(["tox"], check=True) 7 | 8 | 9 | if __name__ == "__main__": 10 | main() 11 | -------------------------------------------------------------------------------- /tox.ini: -------------------------------------------------------------------------------- 1 | [tox] 2 | envlist = py38, py39, py310, py311 3 | 4 | [testenv] 5 | allowlist_externals = poetry 6 | skip_install = true 7 | commands = 8 | poetry install -v # Install dependencies -------------------------------------------------------------------------------- /scripts/publish_pypi.py: -------------------------------------------------------------------------------- 1 | import subprocess 2 | 3 | 4 | def main(): 5 | subprocess.run(["poetry", "publish", "--build"], check=True) 6 | 7 | 8 | if __name__ == "__main__": 9 | main() 10 | -------------------------------------------------------------------------------- /scripts/publish_testpypi.py: -------------------------------------------------------------------------------- 1 | import subprocess 2 | 3 | 4 | def main(): 5 | # Publish to TestPyPI 6 | subprocess.run( 7 | ["poetry", "publish", "--build", "--repository", "testpypi"], check=True 8 | ) 9 | 10 | 11 | if __name__ == "__main__": 12 | main() 13 | -------------------------------------------------------------------------------- /py_diffbro/modules/cmd.py: -------------------------------------------------------------------------------- 1 | import subprocess 2 | 3 | def run_shell_command(command): 4 | process = subprocess.Popen(command, stdout=subprocess.PIPE, shell=True) 5 | output, error = process.communicate() 6 | 7 | if error: 8 | print(f"Error: {error}") 9 | return None 10 | else: 11 | return output 12 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [tool.poetry] 2 | name = "diffbro" 3 | version = "1.0.2" 4 | description = "Your personal AI assistant bro for better code reviews." 5 | authors = ["IndyDevDan "] 6 | readme = "README.md" 7 | packages = [{include = "py_diffbro"}] 8 | exclude = ["scripts/*"] 9 | license = "MIT" 10 | repository = "https://github.com/disler/diffbro.git" 11 | 12 | [tool.poetry.dependencies] 13 | python = "^3.8" 14 | openai = "^0.27.8" 15 | python-dotenv = "^1.0.0" 16 | pydantic = "^2.1.1" 17 | 18 | 19 | [tool.poetry.group.dev.dependencies] 20 | tox = "^4.11.1" 21 | 22 | [build-system] 23 | requires = ["poetry-core"] 24 | build-backend = "poetry.core.masonry.api" 25 | 26 | [tool.poetry.scripts] 27 | diffbro = "py_diffbro.main:main" -------------------------------------------------------------------------------- /py_diffbro/modules/git.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | from .cmd import run_shell_command 3 | 4 | 5 | def get_git_diff(only: List[str], ignore: List[str], branch: str = None): 6 | """ 7 | Returns the git diff as a string 8 | If ignore is specified, diffs all files except those with those extensions 9 | If only is specified, only diffs files with those extensions 10 | If neither are specified, diffs all files 11 | """ 12 | 13 | command = "git diff" 14 | 15 | if branch: 16 | print(f"Diffing against branch {branch}") 17 | command += f" {branch}" 18 | 19 | if only or ignore: 20 | command += " --" 21 | 22 | if ignore: 23 | print(f"Diffing ALL files except those with extensions {ignore}") 24 | files = " ".join(f"':(exclude)**/*{ext}' ':(exclude)*/{ext}" for ext in ignore) 25 | command += f" {files}" 26 | elif only: 27 | print(f"Diffing exclusively files with extensions {only}") 28 | files = " ".join(f"'**/*{ext}' '*{ext}'" for ext in only) 29 | command += f" {files}" 30 | else: 31 | print(f"Diffing all files (no extensions specified))") 32 | 33 | return run_shell_command(command) 34 | -------------------------------------------------------------------------------- /py_diffbro/modules/constants.py: -------------------------------------------------------------------------------- 1 | PROGRAMMING_FILE_EXTENSIONS = [ 2 | ".py", 3 | ".c", 4 | ".cpp", 5 | ".java", 6 | ".cs", 7 | ".php", 8 | ".vb", 9 | ".html", 10 | ".css", 11 | ".js", 12 | ".ts", 13 | ".asp", 14 | ".aspx", 15 | ".cfm", 16 | ".cgi", 17 | ".pl", 18 | ".cer", 19 | ".htm", 20 | ".xhtml", 21 | ".shtml", 22 | ".jsp", 23 | ".jsx", 24 | ".tsx", 25 | ".vue", 26 | ".solid", 27 | ".toml", 28 | ".md", 29 | ".go", 30 | ".rs", 31 | ".swift", 32 | ] 33 | 34 | 35 | DETAILED_DIFFBRO_DESCRIPTION = """ 36 | First export your api key, then run an example below. 37 | 38 | You can get an API key here: https://platform.openai.com/account/api-keys 39 | 40 | Export command 41 | `export OPENAI_API_KEY=` 42 | 43 | Examples: 44 | * I want a chill review on my .py and .js files: 45 | diffbro --chill --only .py .js 46 | 47 | * I'm about to ship production, mission critical UI code, I need a hardcore review on my FE code: 48 | diffbro --chad --model gpt-4 --only .js .jsx .tsx .vue 49 | 50 | * I'm about to a fullstack app and need a comprehensive mid level review on all my code excluding .tsx files: 51 | diffbro --mid --model gpt-4 --ignore .tsx 52 | 53 | * I want legit reviews all the time: 54 | Create a bash alias: alias dbro='diffbro --chad --model gpt-4' 55 | """ 56 | -------------------------------------------------------------------------------- /py_diffbro/modules/llm.py: -------------------------------------------------------------------------------- 1 | """ 2 | This module contains the functions that interact with the OpenAI API. 3 | """ 4 | 5 | import sys 6 | from dotenv import load_dotenv 7 | import os 8 | from typing import Any, Dict 9 | import openai 10 | 11 | # load .env file 12 | load_dotenv() 13 | 14 | # get openai api key 15 | openai.api_key = os.environ.get("OPENAI_API_KEY") 16 | 17 | # ------------------ helpers ------------------ 18 | 19 | 20 | def safe_get(data, dot_chained_keys): 21 | """ 22 | {'a': {'b': [{'c': 1}]}} 23 | safe_get(data, 'a.b.0.c') -> 1 24 | """ 25 | keys = dot_chained_keys.split(".") 26 | for key in keys: 27 | try: 28 | if isinstance(data, list): 29 | data = data[int(key)] 30 | else: 31 | data = data[key] 32 | except (KeyError, TypeError, IndexError): 33 | return None 34 | return data 35 | 36 | 37 | def response_parser(response: Dict[str, Any]): 38 | return safe_get(response, "choices.0.message.content") 39 | 40 | 41 | def make_client(gpt_api_key: str): 42 | return openai 43 | 44 | 45 | # ------------------ content generators ------------------ 46 | 47 | 48 | def prompt(prompt: str, model: str = "gpt-4") -> str: 49 | # validate the openai api key - if it's not valid, raise an error 50 | if not openai.api_key: 51 | sys.exit( 52 | """ 53 | 54 | ERORR: OpenAI API key not found. Please export your key to OPENAI_API_KEY 55 | 56 | Example bash command: 57 | export OPENAI_API_KEY= 58 | """ 59 | ) 60 | 61 | openai_client = openai 62 | 63 | response = openai_client.ChatCompletion.create( 64 | model=model, 65 | messages=[ 66 | { 67 | "role": "user", 68 | "content": prompt, 69 | } 70 | ], 71 | ) 72 | 73 | return response_parser(response) 74 | -------------------------------------------------------------------------------- /py_diffbro/modules/bro.py: -------------------------------------------------------------------------------- 1 | """ 2 | This file contains the text for the various prompts that fuel diffbro functionality 3 | """ 4 | 5 | from typing import Dict 6 | from py_diffbro.modules.app_types import BroMode 7 | 8 | 9 | SUMMARY_BRO_PROMPT = """Summarize the git dif below in a concise, 1-2 sentence description of the changes made. It will be used as the git commit message. Focus on high-level changes not code level details.""" 10 | 11 | CORE_DIFF_BRO_SYSTEM_PROMPT = f"""You're diffbro. A programmer's ultimate peer review bro. 12 | You're here to help your bros review their code before they embarrass themselves in front of the whole team. 13 | You take git diffs and convert them into a format that's easy for your bros to understand and act on. 14 | You're a bro, but you're also a brogrammer. You're a diffbrogrammer. You're diffbro. 15 | 16 | Follow the prompt DETAILS and GIT_DIFF below to help your bro review their code. 17 | """ 18 | 19 | CHILL_BRO_PR_REVIEW_PROMPT = f"""{CORE_DIFF_BRO_SYSTEM_PROMPT} 20 | 21 | DETAILS: 22 | 23 | You're a chill coder bro. Your job is to peer review your bro's code. You look for the big picture stuff and you aren't worried about small details like formatting, naming, pass statements in try blocks, etc. You focus on only code that could lead to critical bugs and nothing else. 24 | You're a chill bro. You're a chill coder bro. You're a chill coder diffbro. You're a chill diffbro.""" 25 | 26 | MID_CHILL_BRO_PR_REVIEW_PROMPT = f"""{CORE_DIFF_BRO_SYSTEM_PROMPT} 27 | 28 | DETAILS: 29 | 30 | You're a mid level coder bro. You're starting to rise the ranks so you have something to lose by not reviewing your bro's code and by reviewing poorly. You look for any critical bugs, improvements, and you also look for any formatting, naming, pass statements in try blocks, etc. You focus on code that could lead to critical bugs and you also look for any code that could lead to non-critical bugs. 31 | You're a mid level bro. You're a mid level coder bro. You're a mid level coder diffbro. You're a mid level diffbro.""" 32 | 33 | CHAD_CHILL_BRO_PR_REVIEW_PROMPT = f"""{CORE_DIFF_BRO_SYSTEM_PROMPT} 34 | 35 | DETAILS: 36 | 37 | You're a chad coder bro. You're at the top of the ranks so you have a lot to lose by not reviewing your bro's code and by reviewing poorly. 38 | You look for any critical bugs, improvements, and you also look for any formatting, naming, pass statements in try blocks, etc. 39 | You focus on code that could lead to critical bugs and you also look for any code that could lead to non-critical bugs. 40 | You also look for any code that could lead to non-critical bugs. 41 | 42 | You diligently report each bug or issue on a low, medium, high scale. You organize them so that the most critical bugs are at the top of the list and the least critical bugs are at the bottom of the list. 43 | Nothing gets past you, you triple check everything. You're a chad bro. You're a chad coder bro. You're a chad coder diffbro. You're a chad diffbro. 44 | """ 45 | 46 | MAP_BRO_MODE_TO_PROMPT: Dict[BroMode, str] = { 47 | BroMode.CHILL: CHILL_BRO_PR_REVIEW_PROMPT, 48 | BroMode.MID: MID_CHILL_BRO_PR_REVIEW_PROMPT, 49 | BroMode.CHAD: CHAD_CHILL_BRO_PR_REVIEW_PROMPT, 50 | } 51 | 52 | 53 | def get_diffbro_prompt(bro_mode: BroMode, git_diff: str) -> str: 54 | """ 55 | Returns the prompt for the given bro mode and git diff 56 | """ 57 | return f"""{MAP_BRO_MODE_TO_PROMPT[bro_mode]} 58 | 59 | GIT_DIFF: 60 | 61 | {git_diff} 62 | 63 | """ 64 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .aider.chat.history.md 2 | .aider.ident.cache.v1 3 | .aider.tags.cache.v1 4 | .aider.input.history 5 | 6 | poetry.lock 7 | 8 | # Byte-compiled / optimized / DLL files 9 | __pycache__/ 10 | *.py[cod] 11 | *$py.class 12 | 13 | # C extensions 14 | *.so 15 | 16 | # Distribution / packaging 17 | .Python 18 | build/ 19 | develop-eggs/ 20 | dist/ 21 | downloads/ 22 | eggs/ 23 | .eggs/ 24 | lib/ 25 | lib64/ 26 | parts/ 27 | sdist/ 28 | var/ 29 | wheels/ 30 | share/python-wheels/ 31 | *.egg-info/ 32 | .installed.cfg 33 | *.egg 34 | MANIFEST 35 | 36 | # PyInstaller 37 | # Usually these files are written by a python script from a template 38 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 39 | *.manifest 40 | *.spec 41 | 42 | # Installer logs 43 | pip-log.txt 44 | pip-delete-this-directory.txt 45 | 46 | # Unit test / coverage reports 47 | htmlcov/ 48 | .tox/ 49 | .nox/ 50 | .coverage 51 | .coverage.* 52 | .cache 53 | nosetests.xml 54 | coverage.xml 55 | *.cover 56 | *.py,cover 57 | .hypothesis/ 58 | .pytest_cache/ 59 | cover/ 60 | 61 | # Translations 62 | *.mo 63 | *.pot 64 | 65 | # Django stuff: 66 | *.log 67 | local_settings.py 68 | db.sqlite3 69 | db.sqlite3-journal 70 | 71 | # Flask stuff: 72 | instance/ 73 | .webassets-cache 74 | 75 | # Scrapy stuff: 76 | .scrapy 77 | 78 | # Sphinx documentation 79 | docs/_build/ 80 | 81 | # PyBuilder 82 | .pybuilder/ 83 | target/ 84 | 85 | # Jupyter Notebook 86 | .ipynb_checkpoints 87 | 88 | # IPython 89 | profile_default/ 90 | ipython_config.py 91 | 92 | # pyenv 93 | # For a library or package, you might want to ignore these files since the code is 94 | # intended to run in multiple environments; otherwise, check them in: 95 | # .python-version 96 | 97 | # pipenv 98 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 99 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 100 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 101 | # install all needed dependencies. 102 | #Pipfile.lock 103 | 104 | # poetry 105 | # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. 106 | # This is especially recommended for binary packages to ensure reproducibility, and is more 107 | # commonly ignored for libraries. 108 | # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control 109 | #poetry.lock 110 | 111 | # pdm 112 | # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control. 113 | #pdm.lock 114 | # pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it 115 | # in version control. 116 | # https://pdm.fming.dev/#use-with-ide 117 | .pdm.toml 118 | 119 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm 120 | __pypackages__/ 121 | 122 | # Celery stuff 123 | celerybeat-schedule 124 | celerybeat.pid 125 | 126 | # SageMath parsed files 127 | *.sage.py 128 | 129 | # Environments 130 | .env 131 | .venv 132 | env/ 133 | venv/ 134 | ENV/ 135 | env.bak/ 136 | venv.bak/ 137 | 138 | # Spyder project settings 139 | .spyderproject 140 | .spyproject 141 | 142 | # Rope project settings 143 | .ropeproject 144 | 145 | # mkdocs documentation 146 | /site 147 | 148 | # mypy 149 | .mypy_cache/ 150 | .dmypy.json 151 | dmypy.json 152 | 153 | # Pyre type checker 154 | .pyre/ 155 | 156 | # pytype static type analyzer 157 | .pytype/ 158 | 159 | # Cython debug symbols 160 | cython_debug/ 161 | 162 | # PyCharm 163 | # JetBrains specific template is maintained in a separate JetBrains.gitignore that can 164 | # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore 165 | # and can be added to the global gitignore or merged into this file. For a more nuclear 166 | # option (not recommended) you can uncomment the following to ignore the entire idea folder. 167 | #.idea/ -------------------------------------------------------------------------------- /py_diffbro/main.py: -------------------------------------------------------------------------------- 1 | import argparse 2 | from py_diffbro.modules.constants import ( 3 | DETAILED_DIFFBRO_DESCRIPTION, 4 | PROGRAMMING_FILE_EXTENSIONS, 5 | ) 6 | from py_diffbro.modules.llm import prompt 7 | from py_diffbro.modules.git import get_git_diff 8 | from py_diffbro.modules.app_types import BroMode 9 | from py_diffbro.modules.bro import SUMMARY_BRO_PROMPT, get_diffbro_prompt 10 | 11 | 12 | def main(): 13 | parser = argparse.ArgumentParser( 14 | description="Diffbro: Your AI Peer Review Bro", 15 | epilog=DETAILED_DIFFBRO_DESCRIPTION, 16 | formatter_class=argparse.RawDescriptionHelpFormatter, 17 | ) 18 | parser.add_argument( 19 | "-c", 20 | "--chill", 21 | action="store_true", 22 | help="Get a chill, jr-level engineer, relaxed diffbro PR review", 23 | ) 24 | parser.add_argument( 25 | "-m", 26 | "--mid", 27 | action="store_true", 28 | help="Get a mid-level engineer, diffbro PR review", 29 | ) 30 | parser.add_argument( 31 | "-d", 32 | "--chad", 33 | action="store_true", 34 | help="Get a chad, sr-level engineer, intense diffbro PR review", 35 | ) 36 | parser.add_argument( 37 | "-o", 38 | "--model", 39 | type=str, 40 | default="gpt-4", 41 | help="GPT model use 'gpt-3.5-turbo' or 'gpt-4'", 42 | ) 43 | parser.add_argument( 44 | "--only", 45 | nargs="*", 46 | default=PROGRAMMING_FILE_EXTENSIONS, 47 | help="Only include files with these extensions", 48 | ) 49 | parser.add_argument( 50 | "--ignore", nargs="*", default=[], help="Ignore files with these extensions" 51 | ) 52 | parser.add_argument( 53 | "-p", "--prompt", type=str, default="", help="Specify a custom prompt" 54 | ) 55 | parser.add_argument( 56 | "-s", "--summarize", action="store_true", help="Summarize the git diff" 57 | ) 58 | parser.add_argument( 59 | "-r", 60 | "--peer-review", 61 | type=str, 62 | default="", 63 | help="Specify the branch to compare the git diff against", 64 | ) 65 | args = parser.parse_args() 66 | 67 | model = args.model 68 | bro_mode: BroMode = BroMode.CHILL 69 | only = args.only 70 | ignore = args.ignore 71 | custom_prompt = args.prompt 72 | summarize = args.summarize 73 | peer_review = args.peer_review 74 | 75 | if args.mid: 76 | bro_mode = BroMode.MID 77 | elif args.chad: 78 | bro_mode = BroMode.CHAD 79 | if model != "gpt-4": 80 | user_input = input( 81 | "Chad mode is engaged. It is suggested to use 'gpt-4' model for optimal results. Do you want to switch to 'gpt-4'? (y/n): " 82 | ) 83 | if user_input.lower() in ["yes", "y"]: 84 | model = "gpt-4" 85 | 86 | git_diff = get_git_diff(only, ignore, peer_review) 87 | 88 | if not git_diff: 89 | print(f"No git diff for diffbro") 90 | return 91 | 92 | print( 93 | f"Building prompt for diffbro in bromode: '{bro_mode}' mode on GPT model '{model}'" 94 | f"{f' with custom prompt: {custom_prompt}' if custom_prompt else ''}" 95 | f"{f' Will generate diff summary.' if summarize else ''}" 96 | ) 97 | 98 | if not custom_prompt: 99 | prompt_text = get_diffbro_prompt(bro_mode, git_diff) 100 | else: 101 | prompt_text = f"{custom_prompt}\n\n{git_diff}" 102 | 103 | print(f"Running DIFFBRO") 104 | 105 | diffbro_response = prompt(prompt_text, model) 106 | 107 | print("\n\nDIFFBRO\n\n", diffbro_response) 108 | 109 | if summarize: 110 | print(f"\n\nSummarizing git diff for diffbro on GPT model '{model}'") 111 | 112 | summary_prompt_text = f"{SUMMARY_BRO_PROMPT}\n\n{git_diff}" 113 | 114 | summary_diffbro_response = prompt(summary_prompt_text, model) 115 | 116 | print("\n\nDIFFBRO SUMMARY\n\n", summary_diffbro_response) 117 | 118 | 119 | if __name__ == "__main__": 120 | main() 121 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # diffbro - AI Powered Peer Reviews 2 | 3 | *Your AI Peer Review Bro* 4 | 5 | Diffbro is a command line tool that gives you AI powered peer reviews on your codebase. Under the hood diffbro utilizes `git diff` and OpenAI's *GPT-3.5-turbo* and *GPT-4* to review your code and provide feedback on your changes. 6 | 7 | Diffbro is best used before you stage and commit your code to your codebase. Diffbro also supports full branch diff PR feedback as if it were an engineer reviewing your merge request (see `--peer-review` flag). Diffbro is designed to help you catch bugs, improve your code quality, and help you ship with confidence. 8 | 9 | ![Diffbro Header](https://firebasestorage.googleapis.com/v0/b/solopreneur-d8361.appspot.com/o/Diffbro%2Fdiffbro.jpg?alt=media&token=fefc8d90-10e2-4091-9b03-957af25aee3b) 10 | 11 | ## Features 12 | 13 | - View all commands, options and examples 14 | - `diffbro --help` 15 | 16 | - Run against local changes 17 | - `diffbro` 18 | 19 | - Run diffbro against a branch and create a PR review 20 | - `diffbro --peer-review main` 21 | 22 | - Different bro modes for chill, to chad engineer level peer reviews 23 | - chill: will review your code like a chill bro (default) 24 | - `diffbro --chill` 25 | - mid: will review your code like a mid level engineer bro 26 | - `diffbro --mid` 27 | - chad: will review your code like a chad, staff engineer bro 28 | - `diffbro --chad` 29 | 30 | - Choose which files to review 31 | - Only .py and .js files 32 | - `diffbro --only .py .js` 33 | - Everything except .py and .js files 34 | - `diffbro --ignore .py .js` 35 | - *Defaults to [".py", ".c", ".cpp", ".java", ".cs", ".php", ".vb", ".html", ".css", ".js", ".ts", ".asp", ".aspx", ".cfm", ".cgi", ".pl", ".cer", ".htm", ".xhtml", ".shtml", ".jsp", ".jsx", ".tsx", ".vue", ".solid", ".toml", ".md", ".go", ".rs", ".swift"]* 36 | 37 | - Choose your gpt model 38 | - `diffbro --model gpt-3.5-turbo` 39 | - `diffbro --model gpt-4` (default) (recommended for production code) 40 | 41 | - Summarize the git diff for a commit message or PR description 42 | - `diffbro --summarize` 43 | 44 | - Override the default prompts with your own custom prompt 45 | - `diffbro --prompt "Below is a git diff of code. Please review and notify only of critical issues. If there are no critical issues, respond with tons of checkbox emojis"` 46 | 47 | - Example command combos 48 | - '*I want a chill review on my .py and .js files*' 49 | - `diffbro --chill --only .py .js` 50 | - '*I'm about to ship production, mission critical UI code, I need a hardcore review on my FE code*' 51 | - `diffbro --chad --model gpt-4 --only .js .jsx .tsx .vue` 52 | - '*I'm about to a fullstack app and need a comprehensive mid level review on all my code excluding .tsx files*' 53 | - `diffbro --mid --model gpt-4 --ignore .tsx` 54 | - '*I want to run my own prompt against my git diff with a summary for the commit massage*' 55 | - `diffbro --prompt "Below is a git diff of code. Please review and notify only of critical issues." --summarize` 56 | - '*I want a quick comparison of my changes against the staging branch with a summary*' 57 | - `diffbro --peer-review staging --model gpt-3.5-turbo --summarize` 58 | - '*I want a mid level code review of all of my .ts files*' 59 | - `diffbro --mid --only .ts` 60 | - '*I want top tier code reviews all the time*' 61 | - Throw this line into your `.bashrc` or `.bash_profile` 62 | - `alias dbro="diffbro --chad --model gpt-4 --summarize"` 63 | - Then, whenever you want a review, just run 64 | - `dbro` 65 | 66 | ## Install & Use 67 | 68 | - Install or switch to [Python 3.11 or 3.10 or 3.9 or 3.8](https://www.python.org/downloads/) 69 | - Check your python version 70 | - `python --version` 71 | 72 | - Install '*stable*' version from [PyPI](https://pypi.org/) 73 | - `pip install --upgrade diffbro` 74 | 75 | - Export your openai api key 76 | - `export OPENAI_API_KEY=` 77 | 78 | - Make changes to your codebase 79 | 80 | - Run diffbro 81 | - `diffbro` 82 | 83 | ### Compare local changes 84 | 85 | - Before you stage and commit, run diffbro 86 | - `diffbro` 87 | 88 | - Implement the feedback from diffbro 89 | 90 | - Commit your code with confidence 91 | 92 | ### Compare branch changes 93 | 94 | - Before you merge, run diffbro 95 | - `diffbro --peer-review main` 96 | 97 | - Implement the feedback from diffbro 98 | 99 | - Merge your code with confidence 100 | 101 | ## Development 102 | 103 | #### Install bleeding edge version test version 104 | 105 | - Install BLEEDING EDGE version from [TestPyPi](https://test.pypi.org/) 106 | - `pip install --upgrade --index-url https://test.pypi.org/simple/ --extra-index-url https://pypi.org/simple diffbro` 107 | 108 | #### Local Dev Commands (excluded from dist) 109 | - run diffbro locally 110 | - `poetry run diffbro` 111 | - test versions 112 | - `poetry run python scripts/run_tox.py` 113 | - publish to test pypi 114 | - `poetry run python scripts/publish_testpypi.py` 115 | - publish to pypi 116 | - `poetry run python scripts/publish_pypi.py` 117 | 118 | ## ROADMAP 119 | 120 | [✅] POC 121 | 122 | [✅] Add GPT model flag 123 | 124 | [✅] Add diff exclusion of large files like poetry.lock from the diff 125 | 126 | [✅] Add cli --only flag to diff only specific file types 127 | 128 | [✅] Add cli --ignore flag to ignore specific file types 129 | 130 | [✅] Deploy version 0.1.0 to TestPyPi 131 | 132 | [✅] Test install version 0.1.0 from TestPyPi 133 | 134 | [✅] Deploy version 0.1.2 to pypy 135 | 136 | [✅] Add help docs 137 | 138 | [✅] Support additional python versions 139 | 140 | [✅] Improve openai_api_key check 141 | 142 | [✅] Chad should always ask to use gpt-4 (simple yes/no prompt) 143 | 144 | [✅] Add custom prompt flag to be run on the diff 145 | `diffbro --prompt "Below is a git diff of code. Please review and notify only of critical issues."` 146 | 147 | [✅] Add summarybro flag that will create a git commit message using the diffbro summary 148 | `diffbro --summarize` -> "Added new feature to the app, fixed a bug, and refactored some code." 149 | 150 | [✅] Add COMPLETE PR review flag which runs diffbro against a branch and creates a PR review 151 | `diffbro --pr main` 152 | 153 | [✅] RELEASE VERSION 1.0.0!!! 154 | 155 | [] Parallelize diffbro and commit summary GPT requests 156 | 157 | [] Add unit tests 158 | 159 | [] What feature would you like to see next? [Submit a feature request](https://github.com/disler/diffbro/issues/new) 160 | 161 | [?] Add token limit check to prevent overage charges 162 | 163 | [?] Add 'AI Devlogs' section to readme w/links to ai devlogs 164 | 165 | [?] Add ~/.diffbro config file support for custom defaults 166 | - if a cli param was specified in the .diffbro file, use that. Add default values to argparse to detect if a cli param was specified (dirty) --------------------------------------------------------------------------------