Skip to content

On a schedule

Find out who didn't log their hours yesterday

Each weekday morning your channel lists the people whose tracked time for the previous day fell short.

Runs
On a schedule
Apps
Harvest
AI
Not needed
Access
read (admin/manager to see others)

Send this to your assistant

Create a ClickRuntime automation: every weekday at 9am, post to #timesheets in Slack the Harvest users who logged less than 6 hours yesterday, with how many hours each one tracked.

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

Time tracking only works if everyone does it, and the people who forget are rarely the ones you would guess. In a ten-person agency, two or three people leave Friday without logging hours, and it is not discovered until invoices go out on the first of the month and the project report looks thin. Reconstructing a week of work from memory three weeks later produces vague, underbilled entries, and the agency absorbs the difference.

Each morning, active Harvest users are listed, their entries for yesterday are totalled, and anyone below the threshold you set is named in a Slack post. The message is short and posted where the team already is, so people can fix their timesheet before they start the new day.

It is meant for agency owners, operations leads and project managers who bill by the hour and need complete timesheets to invoice accurately.

What you get out of it

  • Billable hours are not forgotten

    Every hour that goes unlogged is revenue that is never invoiced. Catching gaps the next morning, while people remember what they did, recovers hours that would otherwise vanish from invoices.

  • Timesheets stay accurate

    An entry written the next day reflects what actually happened, while one reconstructed weeks later is guesswork. Clients who review time detail can see the difference. That keeps the data behind your invoices trustworthy for everyone who reads them.

  • Month-end invoicing runs smoothly

    With timesheets complete each day, nobody is chasing the team for corrections on the last day of the month when invoices are due. Billing goes out on time. Fewer late-night billing sessions also mean the finance person keeps weekends free.

  • Gentle accountability without nagging

    The post names the gap and nothing more. People respond better to a routine, public-in-the-team prompt than to an individual message from a manager. That tone keeps timesheet reminders from feeling like surveillance, which matters for morale in a small team.

  • Project budgets track reality

    Burn rates and budget warnings rely on logged hours. When entries are complete, a project that is running over shows up while there is still time to talk to the client. An overrun spotted mid-project can still be negotiated with the client, while one spotted afterward is a write-off.

  • Cleaner utilization reporting

    Utilization and profitability numbers are only as good as the hours behind them. When gaps are closed daily, a quarterly review of who is billable and who is not rests on facts and not on estimates.

How it works

What happens, step by step

  1. Every weekday at 9am, ClickRuntime lists the active people in your Harvest account.

  2. It adds up the hours each person logged yesterday.

  3. Anyone under your threshold, for example 6 hours, is posted to your Slack channel with how many hours they logged.

Before it runs live

  • Connect Harvest

What you get

RunsOn a schedule
Find out who didn't log their hours yesterdaytoday, 9:00Succeeded
Slack · #timesheetsUnder 6 hours logged on 2026-10-18: • Sam Lee: 3.5h • Jordan Park: 0.0h

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 Harvest 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.
missing_hours_report.pyexample
from collections import defaultdict
from datetime import date, timedelta
from clickruntime import on_trigger, notify, http, credentials

API = "https://api.harvestapp.com/v2"

@on_trigger
def run(event):
    headers = {"Authorization": "Bearer " + credentials.secret("HARVEST_TOKEN"),
               "Harvest-Account-Id": credentials.secret("HARVEST_ACCOUNT_ID"), "User-Agent": "ClickRuntime"}
    yesterday = (date.today() - timedelta(days=1)).isoformat()
    users = http.get(f"{API}/users", headers=headers, params={"is_active": "true"}).json()["users"]
    entries = http.get(f"{API}/time_entries", headers=headers, params={"from": yesterday, "to": yesterday, "per_page": 2000}).json()["time_entries"]
    hours = defaultdict(float)
    for e in entries:
        hours[e["user"]["id"]] += e["hours"]
    short = [f"• {u['first_name']} {u['last_name']}: {hours[u['id']]:.1f}h" for u in users if hours[u["id"]] < 6]
    if short:
        notify.slack(f"Under 6 hours logged on {yesterday}:\n" + "\n".join(short), channel="#timesheets")
    return {"short": len(short)}

FAQ

Common questions

How is the threshold decided?
You choose a minimum number of hours, such as 6 for a full-time employee. Anyone with fewer logged hours for the previous day is listed. Part-time people can be handled with a lower number or excluded.
Are weekends and holidays ignored?
Weekends can be skipped by running the check only on weekdays. Public holidays and time off are harder, so you may want to exclude those people or days through a specific change that you request and approve.
Who sees the names?
Whoever is in the Slack channel you choose. Some teams post to a private managers channel, others to the whole team. Think about which suits your culture, since naming people publicly will not suit everyone.
What permissions does it need?
read (admin/manager to see others). 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 (on a schedule). 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 “Find out who didn't log their hours yesterday” from your assistant

Copy the prompt above, or connect your assistant first. Free plan, no credit card.