
Differed Task Execution
- 23 installs
- 154 repo stars
- Updated July 30, 2026
- sammcj/agentic-coding
Helps with ai & agent building tasks.
About
differed task execution is a Claude Code skill for ai & agent building. It helps solo builders move faster with AI-assisted development.
- differed task execution
- AI & Agent Building
- AI-coding skill
Differed Task Execution by the numbers
- 23 all-time installs (skills.sh)
- +1 installs in the week ending Jul 26, 2026 (Skillselion tracking)
- Ranked #9,978 of 16,556 AI & Agent Building skills by installs in the Skillselion catalog
- Data as of Aug 1, 2026 (Skillselion catalog sync)
npx skills add https://github.com/sammcj/agentic-coding --skill differed-task-executionAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 23 |
|---|---|
| repo stars | ★ 154 |
| Last updated | July 30, 2026 |
| Repository | sammcj/agentic-coding ↗ |
What it does
Helps with ai & agent building tasks.
Files
Differed Task Execution
Delays agent work until a user-specified time using a background timer script, then proceeds with the deferred task.
Script Location
~/.claude/skills/deferred-task-execution/scripts/wait-until.sh
Supported Input Formats
The script accepts one argument in either format:
Duration - relative delay from now:
30s,5m,1h,90m,2h30m,1h15m30s
Clock time - specific time of day:
14:30,9:00,3pm,3:30pm- If the time has already passed today, it waits until that time tomorrow
Workflow
Step 1: Confirm the user's intent
Confirm what task to perform and when. Parse their natural language into a wait-until argument:
| User says | Argument |
|---|---|
| "in 30 minutes" | 30m |
| "in an hour" | 1h |
| "in 2 and a half hours" | 2h30m |
| "at 3pm" | 3pm |
| "at 14:30" | 14:30 |
| "at half past 9" | 9:30am |
The script self-handles timezone via the USER_TZ variable defined at the top of wait-until.sh (defaults to Australia/Melbourne). Clock-time arguments are interpreted in that zone regardless of host TZ. Don't ask the user about timezones unless they mention travelling.
Tell the user exactly what will happen and when the timer will fire. Ask them to confirm before starting.
Step 2: Launch the timer in background
Run the wait script using Bash with run_in_background: true:
~/.claude/skills/deferred-task-execution/scripts/wait-until.sh <argument>Note the task ID from the response -- you need it for the next step.
Step 3: Wait for the timer
Use the TaskOutput tool to block until the timer completes:
- Set
block: true - Set
timeout: 600000(maximum: 10 minutes / 600000ms) - Use the task ID from Step 2
If the wait exceeds 10 minutes: TaskOutput will return before the timer completes because the maximum timeout is 600000ms. Check the output -- if it does not contain "Timer complete", call TaskOutput again with the same task ID and block: true. Repeat until the timer finishes.
Step 4: Execute the deferred task
Once TaskOutput returns output containing "Timer complete. Proceed with deferred task.", carry out whatever work the user requested.
Important Notes
- The agent session must remain open for the timer to work. If the user closes the session, the deferred task will not execute. Warn the user about this.
- For very long waits (multiple hours), remind the user that the session needs to stay active.
- If the user asks to cancel, use
TaskStopwith the background task ID. - Always tell the user the calculated wake time so they know when to expect the action.
#!/usr/bin/env bash
set -euo pipefail
# Waits for a specified duration or until a target clock time, then exits.
# Used by the deferred-task-execution skill to delay agent actions.
#
# Usage:
# wait-until.sh <duration|time>
#
# Duration formats:
# 30s, 5m, 1h, 2h30m, 90m, 1h15m30s
#
# Clock time formats:
# 14:30, 3pm, 3:30pm, 15:00
# If the time has already passed today, waits until that time tomorrow.
#
# Clock-time arguments are interpreted in USER_TZ. Override per-invocation with
# USER_TZ=Australia/Perth wait-until.sh 18:00, or edit the default below.
: "${USER_TZ:=Australia/Melbourne}"
export TZ="${USER_TZ}"
die() {
echo "Error: ${1}" >&2
exit 1
}
[[ $# -ge 1 ]] || die "Usage: wait-until.sh <duration|time>"
input="${1}"
parse_duration_to_seconds() {
local input="${1}"
local total=0
local remaining="${input}"
# Match patterns like 2h30m15s, 5m, 1h, 30s, 90m
while [[ -n "${remaining}" ]]; do
if [[ "${remaining}" =~ ^([0-9]+)h(.*)$ ]]; then
local val="${BASH_REMATCH[1]}"
total=$(( total + val * 3600 ))
remaining="${BASH_REMATCH[2]}"
elif [[ "${remaining}" =~ ^([0-9]+)m(.*)$ ]]; then
local val="${BASH_REMATCH[1]}"
total=$(( total + val * 60 ))
remaining="${BASH_REMATCH[2]}"
elif [[ "${remaining}" =~ ^([0-9]+)s(.*)$ ]]; then
local val="${BASH_REMATCH[1]}"
total=$(( total + val ))
remaining="${BASH_REMATCH[2]}"
else
return 1
fi
done
(( total > 0 )) || return 1
echo "${total}"
}
parse_clock_time_to_seconds() {
local input="${1}"
local hour minute ampm
# Match 3pm, 3:30pm, 3:30PM, 3PM
if [[ "${input}" =~ ^([0-9]{1,2})(:([0-9]{2}))?([aApP][mM])$ ]]; then
hour="${BASH_REMATCH[1]}"
minute="${BASH_REMATCH[3]:-0}"
ampm="${BASH_REMATCH[4],,}" # lowercase
if [[ "${ampm}" == "pm" && "${hour}" -ne 12 ]]; then
hour=$(( hour + 12 ))
elif [[ "${ampm}" == "am" && "${hour}" -eq 12 ]]; then
hour=0
fi
# Match 14:30, 9:00, 09:00
elif [[ "${input}" =~ ^([0-9]{1,2}):([0-9]{2})$ ]]; then
hour="${BASH_REMATCH[1]}"
minute="${BASH_REMATCH[2]}"
else
return 1
fi
(( hour >= 0 && hour <= 23 )) || return 1
(( minute >= 0 && minute <= 59 )) || return 1
local now_epoch
now_epoch=$(date +%s)
# Calculate target epoch for today
local target_epoch
target_epoch=$(date -j -f "%H:%M:%S" "$(printf '%02d:%02d:00' "${hour}" "${minute}")" +%s 2>/dev/null) || \
target_epoch=$(date -d "today ${hour}:${minute}:00" +%s 2>/dev/null) || \
die "Could not parse target time. Ensure date command supports required format."
local delta=$(( target_epoch - now_epoch ))
# If the time has passed today, schedule for tomorrow
if (( delta <= 0 )); then
delta=$(( delta + 86400 ))
fi
echo "${delta}"
}
# Try parsing as duration first, then as clock time
seconds=""
if seconds=$(parse_duration_to_seconds "${input}" 2>/dev/null); then
target_desc="after ${input}"
elif seconds=$(parse_clock_time_to_seconds "${input}" 2>/dev/null); then
target_desc="at ${input}"
else
die "Could not parse '${input}'. Use a duration (e.g. 30m, 1h, 2h30m) or clock time (e.g. 14:30, 3pm)."
fi
# Display wait info
if (( seconds >= 3600 )); then
human_duration="$(( seconds / 3600 ))h$(( (seconds % 3600) / 60 ))m"
elif (( seconds >= 60 )); then
human_duration="$(( seconds / 60 ))m$(( seconds % 60 ))s"
else
human_duration="${seconds}s"
fi
wake_time=$(date -v+"${seconds}"S '+%H:%M:%S %Z' 2>/dev/null) || \
wake_time=$(date -d "+${seconds} seconds" '+%H:%M:%S %Z' 2>/dev/null) || \
wake_time="unknown"
echo "WAITING: ${human_duration} (${seconds}s) - ${target_desc}"
echo "WAKE_TIME: ${wake_time}"
echo "STARTED: $(date '+%Y-%m-%d %H:%M:%S %Z')"
echo "TZ: ${TZ}"
sleep "${seconds}"
echo "READY: $(date '+%Y-%m-%d %H:%M:%S')"
echo "Timer complete. Proceed with deferred task."