Streamline Your GitHub: Effortlessly Delete Repositories with a Python CLI Tool

When you're starting out as a new developer, it's common to create a lot of projects to practice your skills. You might build numerous to-do list applications, fork a variety of starter projects, and develop simple apps to understand different programming concepts. As time goes on, you may lose track of these projects, and years later, you could find yourself with a large number of unused repositories cluttering your GitHub account. Manually reviewing each repository to decide whether to keep or delete it can be a very time-consuming and tedious task. To address this issue and streamline the process, I decided to develop a command-line interface (CLI) application using Python. This tool helps me efficiently manage my repositories, allowing me to quickly identify and remove those that are no longer needed. Below is the code for the CLI app I created:
import requests
import os
import sys
BASE_URL = "https://api.github.com"
def get_repositories(token, page=1, visibility="all"):
"""
Fetches the list of repositories for the authenticated user.
:param token: GitHub authentication token
:param page: Page number for pagination
:param visibility: Filter by visibility (all, public, private)
:return: A list of repository names and boolean indicating if there are more pages
"""
api_url = f"{BASE_URL}/user/repos"
headers = {
"Authorization": f"token {token}",
"Accept": "application/vnd.github+json"
}
params = {
"page": page,
"per_page": 50,
"visibility": visibility
}
response = requests.get(api_url, headers=headers, params=params)
if response.status_code == 200:
repos = [repo["name"] for repo in response.json()]
has_next_page = 'rel="next"' in response.headers.get('Link', '')
return repos, has_next_page
else:
print(f"Failed to fetch repositories. Status code: {response.status_code}")
print(response.json())
return [], False
def delete_repository(token, username, repo_name):
"""
Deletes a GitHub repository for the authenticated user.
:param repo_name: The name of the repository to delete
"""
api_url = f"{BASE_URL}/repos/{username}/{repo_name}"
headers = {
"Authorization": f"token {token}",
"Accept": "application/vnd.github+json"
}
response = requests.delete(api_url, headers=headers)
if response.status_code == 204:
print(f"Repository '{repo_name}' deleted successfully.\n")
elif response.status_code == 404:
print(f"Repository '{repo_name}' not found.\n")
elif response.status_code == 403:
print("Permission denied. Check your token and repository settings.\n")
else:
print(f"Failed to delete repository. Status code: {response.status_code}")
print(response.json())
print()
def main():
token = os.environ.get('GITHUB_TOKEN')
username = os.environ.get('GITHUB_USERNAME')
if not token or not username:
print("Error: GITHUB_TOKEN or GITHUB_USERNAME environment variable not set")
print("Please set it with: export GITHUB_TOKEN='your_token_here'")
print("Please set it with: export GITHUB_USERNAME='your_username_here'")
sys.exit(1)
current_page = 1
visibility = "all"
while True:
if current_page == 1: # Show visibility menu only on first page or after completing operations
print("\nRepository Visibility Options:")
print("1. All repositories")
print("2. Public repositories only")
print("3. Private repositories only")
print("0. Exit")
vis_choice = input("\nSelect visibility option (0-3): ").strip()
if vis_choice == "0":
print("Exiting the program. Goodbye!")
break
elif vis_choice == "1":
visibility = "all"
elif vis_choice == "2":
visibility = "public"
elif vis_choice == "3":
visibility = "private"
else:
print("Invalid choice. Please select a number between 0 and 3.")
continue
print(f"\nFetching your {visibility} repositories (Page {current_page})...\n")
repos, has_next_page = get_repositories(token, current_page, visibility)
if not repos:
print("No repositories found or unable to fetch repositories.")
current_page = 1 # Reset to first page to show visibility menu
continue
print(f"Your {visibility} repositories:")
for idx, repo_name in enumerate(repos, 1):
print(f"{idx}. {repo_name}")
print("\nOptions:")
print("0. Exit")
print("n. Next page") if has_next_page else None
print("p. Previous page") if current_page > 1 else None
print("f. Change visibility filter")
try:
choice = input("\nEnter the numbers of the repositories to delete (comma-separated),\n'n' for next page, 'p' for previous page, 'f' for filter options, or 0 to exit: ").strip()
if choice.lower() == 'f':
current_page = 1 # Reset to first page when changing filter
continue
elif choice.lower() == 'n' and has_next_page:
current_page += 1
continue
elif choice.lower() == 'p' and current_page > 1:
current_page -= 1
continue
elif choice == "0":
print("Exiting the program. Goodbye!")
break
selected_indices = [int(i.strip()) for i in choice.split(",") if i.strip().isdigit()]
invalid_choices = [i for i in selected_indices if i < 1 or i > len(repos)]
if invalid_choices:
print(f"Invalid choices: {invalid_choices}. Please select valid repository numbers.")
continue
selected_repos = [repos[i - 1] for i in selected_indices]
print("\nYou selected the following repositories for deletion:")
for repo in selected_repos:
print(f"- {repo}")
confirm = input("\nAre you sure you want to delete these repositories? This action is irreversible! (yes/no): ").strip().lower()
if confirm == "yes":
for repo in selected_repos:
delete_repository(token, username, repo)
else:
print("Deletion cancelled.")
except ValueError:
print("Invalid input. Please enter a comma-separated list of numbers.")
if __name__ == "__main__":
main()
Now, when you execute this Python command-line application, you have the ability to efficiently delete all your unwanted repositories. This tool provides a user-friendly interface that guides you through the process step-by-step. Upon running the application, you will be presented with a list of all your repositories. You can then select the ones you wish to delete by entering their corresponding numbers. The app will display your selections, giving you a chance to review them. Before proceeding with the deletion, you will be asked to confirm your decision, as this action cannot be undone. If you confirm, the app will proceed to delete the selected repositories. If you decide not to proceed, you can cancel the operation, and no changes will be made. This application streamlines the process of managing your repositories, making it easy to clean up and organize your projects. Here's what the process will look like when you use it:
Fetching your repositories...
Your repositories:
1. repo-one
2. repo-two
3. test-repo
4. sample-repo
Options:
0. Exit
Enter the numbers of the repositories to delete (comma-separated, or 0 to exit): 2,4
You selected the following repositories for deletion:
- repo-two
- sample-repo
Are you sure you want to delete these repositories? This action is irreversible! (yes/no): yes
Repository 'repo-two' deleted successfully.
Repository 'sample-repo' deleted successfully.
Fetching your repositories...
Your repositories:
1. repo-one
2. test-repo
Options:
0. Exit
Enter the numbers of the repositories to delete (comma-separated, or 0 to exit): 0
Exiting the program. Goodbye!
Omar Nava's Blog