GitHub Issue Eraser
github-issue-eraser lists and deletes closed GitHub issues by using the authenticated GitHub CLI account. Before deleting a closed issue that contains images, it looks for the local clone under your home directory by default and backs those images up into the clone's images/ directory.
Deletion is guarded: without --delete, the erase workflow is a dry run.
Behavior
- The script accepts only named options; it does not use positional arguments.
- Only closed issues are listed or deleted.
- Pull requests are naturally excluded by
gh issue list. - Organization mode discovers non-archived repositories with issues enabled.
- Repository mode checks
ORGANIZATION/REPOSITORY. - Image URLs are extracted from the issue body and comments.
- Markdown images, HTML
<img src="...">tags, direct image URLs, and common GitHub issue attachment URLs are detected. - In delete mode, and in dry-run mode with
--image-download, images are saved under:
LOCAL_REPOSITORY/
images/
issue-123-01-image.png
- In default dry-run mode, images are saved under:
/tmp/github-issue-eraser/
ORGANIZATION/
REPOSITORY/
images/
issue-123-01-image.png
- When a previously saved exact image is already present, the script reuses it
instead of saving another copy. The
images/directory contains only the downloaded image files.
If an issue contains images and the local clone cannot be found, the script skips deletion for that issue. If an image download fails, the script also skips deletion for that issue. Issues without images do not require a local clone.
At the end of a dry run or delete run, the script prints a summary with the organization name, number of repositories checked, number of matching local repositories found, and one table row for each inspected closed issue. The table reports the closed issue number, number of images found, number of images saved, and whether all images were downloaded. Issues are deleted only when this image download status is true.
Requirements
- Python 3.10 or newer
- GitHub CLI (
gh) - An authenticated GitHub CLI session:
gh auth login
Building
Testing
Run the unit tests from the project root:
python3 -m unittest discover -s tests -v
Package artifact
Build and validate the package artifacts:
./build-package.sh
This creates the wheel and source distribution under dist/ and checks the package metadata with Twine.
Publish artifact
Publish the generated artifacts to PyPI:
./publish-pypi.sh
The publish script checks that Twine is available, creates a local .venv for Twine when needed, verifies that dist/ contains generated artifacts, and then uploads them. If PyPI returns HTTP 400 because the package version was already published, the script reports that clearly; increment the version in pyproject.toml, rebuild, and publish again.
Install artifact
The software can be installed as follows (using a virtual environment):
python3 -m venv .venv
source .venv/bin/activate
python3 -m pip install github-issue-eraser
Usage
After installing the package, use the github-issue-eraser command. From a source checkout, you can also run ./github-issue-eraser.py.
Help
github-issue-eraser -h
usage: github-issue-eraser [-h] --organization ORGANIZATION [--repository REPOSITORY] [--repos-root REPOS_ROOT] [--limit LIMIT] [--list] [--delete] [--image-download]
List and delete closed GitHub issues after backing up issue images.
options:
-h, --help show this help message and exit
--organization, --org ORGANIZATION
GitHub organization or owner.
--repository REPOSITORY
Repository name inside the organization.
--repos-root REPOS_ROOT
Local repository search root. Default: ~
--limit LIMIT Maximum items to fetch per gh list call. Default: 1000
--list List closed issues without preparing deletion.
--delete Actually delete closed issues. Without this flag, deletion mode is a dry run.
--image-download In dry-run mode, download issue images into each local repository instead of /tmp.
Use cases
List closed issues in every issue-enabled, non-archived repository owned by an organization:
github-issue-eraser --organization ORGANIZATION --list
List closed issues in one repository:
github-issue-eraser --organization ORGANIZATION --repository REPOSITORY --list
Preview deletion work without deleting anything:
github-issue-eraser --organization ORGANIZATION
github-issue-eraser --organization ORGANIZATION --repository REPOSITORY
By default, dry-run image downloads are saved under /tmp/github-issue-eraser
so local repositories are not modified. To execute a dry run while saving images
into each matching local repository's images/ directory, use
--image-download:
github-issue-eraser --organization ORGANIZATION --repository REPOSITORY --image-download
Delete closed issues after image backup checks:
github-issue-eraser --organization ORGANIZATION --delete
github-issue-eraser --organization ORGANIZATION --repository REPOSITORY --delete
Use --repos-root when local clones are not under your home directory:
github-issue-eraser --organization ORGANIZATION --repository REPOSITORY --repos-root ~/work --delete
Use --limit to change how many repositories and issues are fetched per GitHub
CLI list call:
github-issue-eraser --organization ORGANIZATION --limit 2000 --list
Examples
Dry-run output includes the repositories checked, closed issues found, local repository path, image URLs to download, and the action that would be taken:
github-issue-eraser --organization kaizten --repository tools
After reviewing the dry run, run with --delete to actually remove closed
issues:
github-issue-eraser --organization kaizten --repository tools --delete
Metadata
Release files for github-issue-eraser 0.0.2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| github_issue_eraser-0.0.2.tar.gz | 14.7 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| github_issue_eraser-0.0.2-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 25.8 kB
Release files / github_issue_eraser-0.0.2.tar.gz
| Download URL | github_issue_eraser-0.0.2.tar.gz |
|---|---|
| Size | 14.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
56fa4f17c87bd897165b3a6fe38c8b910ad3887fa08ea83b4d46b06ce164f7d1
|
|
BLAKE2b-256 checksum How to use checksums |
5e58fd37750fd6876ae878030b93ebeed7e9142070261d9afa6ec7da149b909c
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.4
|
Release files / github_issue_eraser-0.0.2-py3-none-any.whl
| Download URL | github_issue_eraser-0.0.2-py3-none-any.whl |
|---|---|
| Size | 11.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
1f0c86c9665e9592c0c2542f96edeb17acf5ae4a12cc7ba915b4502b9bc20aeb
|
|
BLAKE2b-256 checksum How to use checksums |
8dbade43a2720fe0bdc780903260f19c742154808f8ddd85c828567d60784fb2
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.4
|