Skip to content

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.

Paste it into your assistant. It tells you what it will send or change before it runs live.

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

  1. On the first of each month, ClickRuntime signs in to Docker Hub and lists every tag in your repositories.

  2. It keeps the tags nobody has pulled in the last 90 days, plus any that have never been pulled.

  3. 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

RunsMonthly
List tags nobody has pulled in 90 daystoday, 9:00Succeeded
Email · Stale tagsapi: v1.8.0 last pulled 2026-04-02 test-build last pulled never

Build your own

Need it to work differently?

This template is a starting point. Copy the prompt and change it, or describe a different automation from scratch, with your own conditions, more apps or an AI step. Your assistant writes it, tests it and runs it on ClickRuntime.
  • 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

This is the Python script that runs each time the automation starts. Your AI assistant writes it for you when you send the prompt, and you allow each step in your assistant. To change how the automation works, describe the change to your assistant and it updates the script for you. For every function it can use, see the script reference.
get_a_monthly_list_of_stale_tags.pyexample
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?
A tag is stale if its last pulled date is older than 90 days, or if it has never been pulled. The 90-day cutoff is adjustable, so a team that releases quarterly may prefer 180 days to avoid listing active tags.
Does it delete anything?
No. It only emails a list. Deleting tags is a deliberate step you take in Docker Hub, which prevents the automation from removing a version that a customer depends on but only rarely pulls, such as an old long-term release.
What kind of Docker Hub token is needed?
A personal access token with read access is enough to list repositories and tags. It is exchanged for a short-lived login token at each run, and the token is stored as a secret rather than appearing in the email.
What permissions does it need?
read. Nothing else in your accounts is used.
Does it need AI?
No. It runs without AI, so it doesn't use your plan's AI allowance.
How many runs does it use?
One run each time it runs (monthly). Checks that find nothing to do and stop right away aren't counted.
Can I change how it works?
Yes. Describe the change to your AI assistant, for example a different schedule, channel or filter. It updates the automation, tests it and tells you what changed.

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.