Monthly
List tags nobody has pulled in 90 days
On the first of each month you get the tags no one has pulled in 90 days or ever, ready for a clean-up.
- Runs
- Monthly
- Apps
- Docker Hub
- AI
- Not needed
- Access
- read
Send this to your assistant
Create a ClickRuntime automation: on the 1st of every month, email me the tags in my Docker Hub repositories that were last pulled more than 90 days ago or never, grouped by repository. Don't delete anything.
First time? Adding ClickRuntime to your assistant takes about two minutes.
Why use it
Why teams use this automation
A team that has pushed images to Docker Hub for years ends up with hundreds of tags nobody pulls: build numbers, feature branches, old release candidates. They clutter the repository page, make it harder for users to find the right version and, on private repositories, can count against storage limits. Deciding what to delete means opening every repository and guessing from tag names, so cleanup is postponed indefinitely.
Once a month the automation exchanges your personal access token for a login token, lists your repositories and tags, and keeps those whose last pulled date is older than 90 days or empty. It emails the list, grouped by repository, so you can delete with confidence in one sitting.
Platform teams, open-source maintainers and anyone with a long-lived Docker Hub organization benefit most.
What you get out of it
Cleanup based on real usage
Tag names suggest what matters, but pull dates show what is actually used. A tag nobody has pulled in 90 days is a safe candidate for deletion, while a quiet but critical one is easy to spot and keep.
Smaller, clearer repository pages
Fewer stale tags make it easier for users to find the supported version. Newcomers stop pulling an old release candidate by accident and then filing bugs against a build that was never meant to be used.
Lower storage use on private repositories
Plans that count private storage reward tidy repositories. Removing forgotten images keeps usage under the plan limit, which can delay an upgrade you would otherwise have to pay for just to hold images nobody uses.
Never-pulled tags revealed
Tags with no pull date at all are listed too. These are often failed builds or experiments that were pushed and forgotten, and they are the easiest ones to remove because nobody ever depended on them.
A monthly rhythm instead of a big purge
Small regular cleanups are less risky than a once-a-year deletion spree. You review a short list each month while you still remember why those tags existed and who might have used them.
How it works
What happens, step by step
On the first of each month, ClickRuntime signs in to Docker Hub and lists every tag in your repositories.
It keeps the tags nobody has pulled in the last 90 days, plus any that have never been pulled.
You get one email grouped by repository showing each stale tag and when it was last pulled, ready for a clean-up.
Before it runs live
- Connect Docker Hub
What you get
Build your own
Need it to work differently?
Your own rules
Conditions, thresholds, filters and exceptions, written the way you'd explain them to a colleague.
Any number of apps
One automation can read from one app and update several others. Over 248 apps are ready, and anything with an API works too.
AI where it helps
Summaries, classification, extraction and drafts use ClickRuntime's built-in AI, with no extra key.
On a schedule or on each event
Runs as often as every 5 minutes, or the moment an app sends an event, and keeps track of what it already handled.
Changes you can ask for
- Run it at a different time, more or less often, or only on weekdays
- Add an AI step, for example to summarize, sort or draft a reply
- Add another app, for example also send it to Slack
- Combine it with other Docker Hub steps into one automation
Under the hood
The code that runs this automation
from datetime import datetime, timedelta, timezone
from clickruntime import on_trigger, credentials, http, notify
NAMESPACE = "acme"
HUB = "https://hub.docker.com/v2"
@on_trigger
def run(event):
token = http.post(f"{HUB}/auth/token", json={"identifier": NAMESPACE,
"secret": credentials.secret("DOCKER_HUB_TOKEN")}).json()["access_token"]
headers = {"Authorization": f"Bearer {token}"}
cutoff = (datetime.now(timezone.utc) - timedelta(days=90)).isoformat()
repos = http.get(f"{HUB}/namespaces/{NAMESPACE}/repositories", params={"page_size": 100},
headers=headers).json()["results"]
lines, total = [], 0
for r in repos:
tags = http.get(f"{HUB}/namespaces/{NAMESPACE}/repositories/{r['name']}/tags",
params={"page_size": 100}, headers=headers).json()["results"]
stale = [t for t in tags if not t.get("tag_last_pulled") or t["tag_last_pulled"] < cutoff]
if stale:
total += len(stale)
lines.append(f"{r['name']}:")
lines += [f" {t['name']} last pulled {(t.get('tag_last_pulled') or 'never')[:10]}" for t in stale]
notify.email_me(f"{total} Docker Hub tags not pulled in 90 days", "\n".join(lines) or "No stale tags.")
return {"stale": total}FAQ
Common questions
What counts as a stale tag?
Does it delete anything?
What kind of Docker Hub token is needed?
What permissions does it need?
Does it need AI?
How many runs does it use?
Can I change how it works?
Related
You might also like
Get a weekly list of your repos and tags
Every Monday you get each repository's latest tags and when they were pushed.
See how it worksTrack weekly pulls for each image
Each week you see every repository's total pulls and how much that grew since the previous week.
See how it worksGet a message when a new tag is pushed
Each time a tag is pushed to your repository, you see the tag, who pushed it and the repo right away.
See how it worksKeep exploring
Set up “List tags nobody has pulled in 90 days” from your assistant
Copy the prompt above, or connect your assistant first. Free plan, no credit card.