{"id":51440857,"url":"https://github.com/ghcr-manager/ghcr-cleanup-manager","last_synced_at":"2026-07-05T11:31:01.671Z","repository":{"id":364809230,"uuid":"1268419930","full_name":"ghcr-manager/ghcr-cleanup-manager","owner":"ghcr-manager","description":"GHCR cleanup, scanning, and visualization for GitHub Container Registry packages","archived":false,"fork":false,"pushed_at":"2026-07-02T11:05:01.000Z","size":4187,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-07-02T11:05:35.776Z","etag":null,"topics":["container-image","container-registry","docker-image","ghcr","ghcr-audit","ghcr-cleanup","ghcr-io","ghcr-io-cleanup","ghcr-visualization","ghcr-visualize","github-action","github-container-registry","image-cleaner","image-cleanup","multi-arch","package-cleanup"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ghcr-manager.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null}},"created_at":"2026-06-13T14:09:06.000Z","updated_at":"2026-07-02T11:01:37.000Z","dependencies_parsed_at":null,"dependency_job_id":"8aee71bb-8192-4ea4-aedc-0c893dd726ba","html_url":"https://github.com/ghcr-manager/ghcr-cleanup-manager","commit_stats":null,"previous_names":["ghcr-manager/ghcr-cleanup-manager"],"tags_count":6,"template":false,"template_full_name":null,"purl":"pkg:github/ghcr-manager/ghcr-cleanup-manager","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ghcr-manager%2Fghcr-cleanup-manager","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ghcr-manager%2Fghcr-cleanup-manager/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ghcr-manager%2Fghcr-cleanup-manager/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ghcr-manager%2Fghcr-cleanup-manager/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ghcr-manager","download_url":"https://codeload.github.com/ghcr-manager/ghcr-cleanup-manager/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ghcr-manager%2Fghcr-cleanup-manager/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35153107,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-07-05T02:00:06.290Z","response_time":100,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["container-image","container-registry","docker-image","ghcr","ghcr-audit","ghcr-cleanup","ghcr-io","ghcr-io-cleanup","ghcr-visualization","ghcr-visualize","github-action","github-container-registry","image-cleaner","image-cleanup","multi-arch","package-cleanup"],"created_at":"2026-07-05T11:31:00.610Z","updated_at":"2026-07-05T11:31:01.658Z","avatar_url":"https://github.com/ghcr-manager.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# GHCR Cleanup Manager\n\n[![GitHub Marketplace](https://img.shields.io/badge/marketplace-ghcr--cleanup--manager-blue?logo=github\u0026labelColor=333\u0026style=flat-square)](https://github.com/marketplace/actions/ghcr-manager)\n[![Release](https://img.shields.io/github/v/release/ghcr-manager/ghcr-cleanup-manager?style=flat-square)](https://github.com/ghcr-manager/ghcr-cleanup-manager/releases)\n[![Immutable Releases](https://img.shields.io/badge/releases-immutable-blue?labelColor=333)](https://docs.github.com/en/code-security/supply-chain-security/understanding-your-software-supply-chain/immutable-releases)\n[![Tests](https://img.shields.io/github/actions/workflow/status/ghcr-manager/ghcr-cleanup-manager/.github/workflows/ci_change-validation.yml?branch=main\u0026label=test\u0026style=flat-square)](https://github.com/ghcr-manager/ghcr-cleanup-manager/actions/workflows/ci_change-validation.yml)\n\nGHCR Cleanup Manager is a GHCR cleanup action for GitHub Container Registry packages.\n\nGHCR Cleanup Manager is a GitHub Action for:\n\n- clean GHCR packages including tagged and untagged images\n- preview cleanup with `dry-run` before making changes\n- scan GHCR packages into SQLite database artifacts\n- visualize GHCR package graphs and their changes with the\n  [visualizer](https://github.com/ghcr-manager/ghcr-cleanup-manager/blob/main/visualizer/README.md)\n\nIt is built for safe GHCR cleanup on OCI package graphs, including multi-arch images, attestations, cosign signatures,\nand other referrers that simpler GHCR cleanup actions often mishandle.\n\n[![Example compare view: red-bordered manifests are present in the older scan and removed in the newer one.](https://raw.githubusercontent.com/ghcr-manager/ghcr-cleanup-manager/main/docs/images/visualizer/graph-2images-cosign--wide.png \"Example compare view: red-bordered manifests are present in the older scan and removed in the newer one.\")](https://github.com/ghcr-manager/ghcr-cleanup-manager/blob/main/docs/images/visualizer/graph-2images-cosign--wide.png)\n\n_Example graph compare view: red-bordered manifests are present in the older scan and removed in the newer one._\n\n## Quick Start\n\nFor a first run, start with `cleanup` in `dry-run` mode.\n\n```yaml\njobs:\n  cleanup:\n    runs-on: ubuntu-latest\n    permissions:\n      contents: read\n      packages: read\n      actions: write\n    concurrency:\n      group: ghcr-cleanup-manager__OWNER__PACKAGE\n    steps:\n      - uses: actions/checkout@v6\n\n      - name: Preview GHCR cleanup\n        id: ghcr-cleanup-manager\n        uses: ghcr-manager/ghcr-cleanup-manager@v1.1.5\n        with:\n          command: cleanup\n          token: ${{ github.token }}\n          owner: OWNER\n          package: PACKAGE\n          dry-run: true\n          delete-untagged: true\n          keep-n-tagged: 10\n          exclude-tags: |\n            latest\n          upload-artifacts: true\n```\n\n\u003e Permission notes:\n\u003e\n\u003e - `scan` and `cleanup` dry-runs need `packages: read`\n\u003e - live `cleanup` that mutates GHCR needs `packages: write`\n\u003e - artifact upload needs `actions: write`\n\nAfter the run:\n\n1. Open the GitHub step summary for the action run.\n2. Review which tags matched and which roots would be deleted, untagged, or blocked.\n3. Only download the DB artifact if you need deeper inspection.\n\n## Commands\n\nThe action supports two commands:\n\n- `cleanup`: Cleans using filters; use `dry-run` to preview the result\n- `scan`: Scans one package and uploads the resulting DB artifact\n\n### Purpose of commands\n\n- `cleanup`: Normal entry point for registry maintenance\n- `scan`: For investigation and audit\n\n## Common Usage\n\n### Preview cleanup\n\n```yaml\n- uses: ghcr-manager/ghcr-cleanup-manager@v1.1.5\n  with:\n    command: cleanup\n    token: ${{ github.token }}\n    owner: OWNER\n    package: PACKAGE\n    dry-run: true\n    delete-tags: |\n      pr-.*\n    use-regex: true\n    older-than: 30 days\n    keep-n-tagged: 5\n    exclude-tags: |\n      latest\n      stable\n    upload-artifacts: true\n```\n\n### Apply cleanup\n\n```yaml\n- uses: ghcr-manager/ghcr-cleanup-manager@v1.1.5\n  with:\n    command: cleanup\n    token: ${{ github.token }}\n    owner: OWNER\n    package: PACKAGE\n    delete-untagged: true\n    keep-n-tagged: 10\n    upload-artifacts: true\n    scan-after-cleanup: true\n```\n\nIf `scan-after-cleanup` is `true`, `cleanup` performs a second scan so the uploaded DB reflects post-mutation state.\n\nNote: the second scan only runs if cleanup actually makes changes.\n\nLive cleanup permission note: change the workflow permission from `packages: read` to `packages: write` before turning\noff `dry-run`.\n\n### Scan one package\n\n```yaml\n- uses: ghcr-manager/ghcr-cleanup-manager@v1.1.5\n  with:\n    command: scan\n    token: ${{ github.token }}\n    owner: OWNER\n    package: PACKAGE\n```\n\n`scan` always uploads a DB artifact.\n\n## Inputs\n\n\u003c!-- markdownlint-disable MD013 MD060 --\u003e\n\n| Input                        | Description                         | Cmds | Required | Default                        |\n| ---------------------------- | ----------------------------------- | ---- | -------- | ------------------------------ |\n| `command`                    | `scan` or `cleanup`                 | all  | Yes      |                                |\n| `token`                      | GitHub token for API calls          | all  | Yes      | `${{ github.token }}`          |\n| `owner`                      | Package owner                       | all  | Yes      |                                |\n| `package`                    | Package name                        | all  | Yes      |                                |\n| `db-path`                    | Local SQLite DB path                | s,c  | No       |                                |\n| `upload-artifacts`           | Upload DB and summary artifacts     | s,c  | No       | `false`                        |\n| `scan-after-cleanup`         | Run a second scan after cleanup     | c    | No       | `false`                        |\n| `db-artifact-retention-days` | Override artifact retention days    | s,c  | No       | `${{ github.retention_days }}` |\n| `delete-tags`                | Newline-separated tags to delete    | c    | No       |                                |\n| `exclude-tags`               | Newline-separated tags to exclude   | c    | No       |                                |\n| `keep-n-tagged`              | Keep newest tagged roots            | c    | No       |                                |\n| `keep-n-untagged`            | Keep newest untagged roots          | c    | No       |                                |\n| `delete-untagged`            | Delete untagged roots               | c    | No       | `false`                        |\n| `delete-ghost-images`        | Delete ghost multi-arch roots       | c    | No       | `false`                        |\n| `delete-partial-images`      | Delete partial multi-arch roots     | c    | No       | `false`                        |\n| `delete-orphaned-images`     | Delete orphaned digest-derived tags | c    | No       | `false`                        |\n| `older-than`                 | Age cutoff for cleanup selectors    | c    | No       |                                |\n| `use-regex`                  | Use regex for cleanup tag selectors | c    | No       | `false`                        |\n| `dry-run`                    | Show changes without mutating GHCR  | c    | No       | `false`                        |\n| `log-level`                  | CLI log level                       | all  | No       | `info`                         |\n\n\u003c!-- markdownlint-enable MD013 MD060 --\u003e\n\n`Cmds`: `s` = `scan`, `c` = `cleanup`\n\nCleanup command notes:\n\n- Tagged selector families may be combined with `delete-untagged`.\n- `exclude-tags` requires at least one tagged selector family.\n- `delete-untagged` and `keep-n-untagged` cannot be combined.\n- `older-than` takes one integer plus one unit.\n  - Supported `older-than` units: `minutes`, `hours`, `days`, `weeks`, `months`, `years`.\n  - Example values: `30 days`, `2 hours`, `1 month`.\n\n## Outputs\n\n| Output              | Description                          |\n| ------------------- | ------------------------------------ |\n| `db-path`           | SQLite DB path on the runner         |\n| `summary-json-path` | Summary JSON file path for `cleanup` |\n\n## Artifacts\n\nWhen artifacts are enabled:\n\n- `scan` always uploads one SQLite DB artifact\n- `cleanup` optionally uploads the DB artifact and a cleanup summary JSON artifact\n\nCurrent naming:\n\n| Artifact type        | Filename pattern                                    |\n| -------------------- | --------------------------------------------------- |\n| scan or cleanup DB   | `${OWNER}__${PACKAGE}.sqlite`                       |\n| cleanup summary JSON | `${OWNER}__${PACKAGE}.sqlite--cleanup-summary.json` |\n\n## Documentation Map\n\n- [GitHub Action usage](https://github.com/ghcr-manager/ghcr-cleanup-manager/blob/main/docs/action-usage.md): action\n  commands, including `cleanup` and `scan`\n- [Cleanup behavior](https://github.com/ghcr-manager/ghcr-cleanup-manager/blob/main/docs/cleanup-behavior.md): how\n  cleanup protects retained tags and handles shared graphs\n- [ghcr-cleanup-manager-visualizer](https://github.com/ghcr-manager/ghcr-cleanup-manager/blob/main/visualizer/README.md):\n  local graph inspection and scan-to-scan comparison\n- [Multi-package workflows](https://github.com/ghcr-manager/ghcr-cleanup-manager/blob/main/docs/db-merge-workflows.md):\n  cleaning up multiple packages with one combined DB\n- [SQLite schema guide](https://github.com/ghcr-manager/ghcr-cleanup-manager/blob/main/docs/schema-description.md):\n  practical explanation of the SQLite schema\n- [CLI usage](https://github.com/ghcr-manager/ghcr-cleanup-manager/blob/main/docs/cli-usage.md): companion CLI usage\n\n## Explore A Real Scenario DB\n\nThe release assets also include one merged SQLite DB from GHCR Cleanup Manager's live scenario workflows. You can use it\nas a quick visualizer demo and as a compact way to inspect dozens of real cleanup and graph cases.\n\n```sh\ncurl -LO https://github.com/ghcr-manager/ghcr-cleanup-manager/releases/latest/download/ghcr-cleanup-manager-release-scenarios.sqlite\nnpx ghcr-cleanup-manager-visualizer --db ./ghcr-cleanup-manager-release-scenarios.sqlite\n```\n\nDocker image available:\n[visualizer Docker usage](https://github.com/ghcr-manager/ghcr-cleanup-manager/blob/main/visualizer/README.md#docker).\n\nFor a first look in the visualizer, start with:\n\n- owner: `ghcr-cleanup-manager-test`\n- package: select one with `2images` or `2multiarch` in the name\n- tag search: `image` or `multiarch`\n\nFor more details, see [visualizer](https://github.com/ghcr-manager/ghcr-cleanup-manager/blob/main/visualizer/README.md)\nand [test-scenarios](https://github.com/ghcr-manager/ghcr-cleanup-manager/blob/main/docs/test/scenarios.md).\n\n## Cleanup Behavior\n\nCleanup is tag-based for both selection and protection. Use tags to say what should be cleaned up, and use retained tags\nto keep image and multi-arch graphs protected.\n\nManifests reachable from retained tags stay protected. Manifests no longer reachable from any retained tag may be\nremoved during cleanup. If you pull images by digest, make sure those digests are still reachable through tags that your\ncleanup rules keep.\n\nFor the full explanation and graph examples, see\n[cleanup-behavior](https://github.com/ghcr-manager/ghcr-cleanup-manager/blob/main/docs/cleanup-behavior.md).\n\n## Project\n\nMain project and issue tracker:\n\n- Repository: \u003chttps://github.com/ghcr-manager/ghcr-cleanup-manager\u003e\n- Issues: \u003chttps://github.com/ghcr-manager/ghcr-cleanup-manager/issues\u003e\n\n## Similar Tools\n\n- [ghcr-manager/ghcr-untag-action](https://github.com/ghcr-manager/ghcr-untag-action): focused tag removal without the\n  broader scan and cleanup workflow.\n- [dataaxiom/ghcr-cleanup-action](https://github.com/dataaxiom/ghcr-cleanup-action): another GHCR cleanup action with a\n  similar problem focus.\n- [mkoepf/ghcrctl](https://github.com/mkoepf/ghcrctl): CLI tooling for working with GHCR packages and graph deletions.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fghcr-manager%2Fghcr-cleanup-manager","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fghcr-manager%2Fghcr-cleanup-manager","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fghcr-manager%2Fghcr-cleanup-manager/lists"}