Skill: loui1979/remind-me-2-1-0 (version 1.0.0)

--- name: remind-me description: Set reminders using natural language. Automatically creates one-time cron jobs and logs to markdown. metadata: {"clawdbot":{"emoji":"⏰","requires":{"bins":["bash","date"]}}} --- # Remind Me Natural language reminders that fire automatically. Uses cron for scheduling, markdown for logging. ## Usage ### One-Time Reminders Just ask naturally: - "Remind me to pay for Gumroad later today" - "Remind me to call mom tomorrow at 3pm" - "Remind me in 2 hours to check the oven" - "Remind me next Monday at 9am about the meeting" ### Recurring Reminders For repeating reminders: - "Remind me every hour to stretch" - "Remind me every day at 9am to check email" - "Remind me every Monday at 2pm about the meeting" - "Remind me weekly to submit timesheet" ## How It Works 1. Parse the time from your message 2. Create a one-time cron job with `--at` 3. Log to `/home/julian/clawd/reminders.md` for history 4. At the scheduled time, you get a message ## Time Parsing ### One-Time Reminders **Relative:** - "in 5 minutes" / "in 2 hours" / "in 3 days" - "later today" → 17:00 today - "this afternoon" → 15:00 today - "tonight" → 20:00 today **Absolute:** - "tomorrow" → tomorrow 9am - "tomorrow at 3pm" → tomorrow 15:00 - "next Monday" → next Monday 9am - "next Monday at 2pm" → next Monday 14:00 **Dates:** - "January 15" → Jan 15 at 9am - "Jan 15 at 3pm" → Jan 15 at 15:00 - "2026-01-15" → Jan 15 at 9am - "2026-01-15 14:30" → Jan 15 at 14:30 ### Recurring Reminders **Intervals:** - "every 30 minutes" - "every 2 hours" **Daily:** - "daily at 9am" - "every day at 3pm" **Weekly:** - "weekly" → every Monday at 9am - "every Monday at 2pm" - "every Friday at 5pm" ## Reminder Log All reminders are logged to `/home/julian/clawd/reminders.md`: ```markdown - [scheduled] 2026-01-06 17:00 | Pay for Gumroad (id: abc123) - [recurring] every 2h | Stand up and stretch (id: def456) - [recurring] cron: 0 9 * * 1 | Weekly meeting (id: ghi789) ``` **Status:** - `[scheduled]` — one-time reminder waiting to fire - `[recurring]` — repeating reminder (active) - `[sent]` — one-time reminder already delivered ## Manual Commands ```bash # List pending reminders cron list # View reminder log cat /home/julian/clawd/reminders.md # Remove a scheduled reminder cron rm <job-id> ``` ## Agent Implementation ### One-Time Reminders When the user says "remind me to X at Y": ```bash bash /home/julian/clawd/skills/remind-me/create-reminder.sh "X" "Y" ``` **Examples:** ```bash bash /home/julian/clawd/skills/remind-me/create-reminder.sh "Pay for Gumroad" "later today" bash /home/julian/clawd/skills/remind-me/create-reminder.sh "Call dentist" "tomorrow at 3pm" bash /home/julian/clawd/skills/remind-me/create-reminder.sh "Check email" "in 2 hours" ``` ### Recurring Reminders When the user says "remind me every X to Y": ```bash bash /home/julian/clawd/skills/remind-me/create-recurring.sh "Y" "every X" ``` **Examples:** ```bash bash /home/julian/clawd/skills/remind-me/create-recurring.sh "Stand up and stretch" "every 2 hours" bash /home/julian/clawd/skills/remind-me/create-recurring.sh "Check email" "daily at 9am" bash /home/julian/clawd/skills/remind-me/create-recurring.sh "Weekly team meeting" "every Monday at 2pm" ``` Both scripts automatically: 1. Parse the time/schedule 2. Create a cron job (one-time with `--at` or recurring with `--every`/`--cron`) 3. Log to `/home/julian/clawd/reminders.md` 4. Return confirmation with job ID

path: check-reminders.sh
content: #!/bin/bash
# Check reminders and output due ones (to be sent by the agent)

REMINDERS_FILE="/home/julian/clawd/reminders.md"
NOW_EPOCH=$(date +%s)

# Exit if no reminders file
[[ ! -f "$REMINDERS_FILE" ]] && exit 0

DUE_REMINDERS=()

# Process each unchecked reminder
while IFS= read -r line; do
    # Extract: "- [ ] 2026-01-06 14:30 | Pay for Gumroad"
    datetime=$(echo "$line" | sed -n 's/^- \[ \] \(.*\) | .*/\1/p')
    message=$(echo "$line" | sed -n 's/^- \[ \] .* | \(.*\)/\1/p')
    
    # Skip if parsing failed
    [[ -z "$datetime" ]] || [[ -z "$message" ]] && continue
    
    # Handle shortcuts
    datetime=$(echo "$datetime" | sed "s/^today/$(date '+%Y-%m-%d')/")
    datetime=$(echo "$datetime" | sed "s/^tomorrow/$(date -d 'tomorrow' '+%Y-%m-%d')/")
    
    # Add default time if missing
    if ! echo "$datetime" | grep -q ":"; then
        datetime="$datetime 09:00"
    fi
    
    # Parse to epoch
    reminder_epoch=$(date -d "$datetime" +%s 2>/dev/null)
    
    # Skip if date parsing failed
    [[ -z "$reminder_epoch" ]] && continue
    
    # Check if due
    if [[ $NOW_EPOCH -ge $reminder_epoch ]]; then
        DUE_REMINDERS+=("$message")
        # Mark as done by replacing [ ] with [x]
        escaped_datetime=$(echo "$datetime" | sed 's/[]\/$*.^[]/\\&/g')
        escaped_message=$(echo "$message" | sed 's/[]\/$*.^[]/\\&/g')
        sed -i "s/^- \[ \] $escaped_datetime | $escaped_message$/- [x] $escaped_datetime | $escaped_message/" "$REMINDERS_FILE"
    fi
done < <(grep "^- \[ \]" "$REMINDERS_FILE")

# Output due reminders
if [[ ${#DUE_REMINDERS[@]} -gt 0 ]]; then
    for reminder in "${DUE_REMINDERS[@]}"; do
        echo "⏰ $reminder"
    done
fi

# Clean up reminders older than 24 hours
while IFS= read -r line; do
    datetime=$(echo "$line" | sed -n 's/^- \[x\] \(.*\) | .*/\1/p')
    reminder_epoch=$(date -d "$datetime" +%s 2>/dev/null)
    [[ -z "$reminder_epoch" ]] && continue
    
    age_hours=$(( (NOW_EPOCH - reminder_epoch) / 3600 ))
    if [[ $age_hours -gt 24 ]]; then
        # Delete old completed reminders
        escaped_line=$(echo "$line" | sed 's/[\/&]/\\&/g')
        sed -i "/^${escaped_line}$/d" "$REMINDERS_FILE"
    fi
done < <(grep "^- \[x\]" "$REMINDERS_FILE")


path: create-recurring.sh
content: #!/bin/bash
# Create a recurring reminder
# Usage: create-recurring.sh "message" "schedule"

MESSAGE="$1"
SCHEDULE="$2"
REMINDERS_FILE="/home/julian/clawd/reminders.md"
TIMEZONE="Europe/Warsaw"

[[ -z "$MESSAGE" ]] && echo "Error: No message provided" && exit 1
[[ -z "$SCHEDULE" ]] && echo "Error: No schedule provided" && exit 1

# Parse schedule to cron expression or duration
parse_schedule() {
    local input="$1"
    
    # Every X minutes/hours
    if [[ "$input" =~ every[[:space:]]+([0-9]+)[[:space:]]+(minute|hour)s? ]]; then
        local amount="${BASH_REMATCH[1]}"
        local unit="${BASH_REMATCH[2]}"
        case "$unit" in
            minute) echo "duration:$((amount))m" ;;
            hour) echo "duration:$((amount))h" ;;
        esac
        return
    fi
    
    # Daily at specific time
    if [[ "$input" =~ (daily|every[[:space:]]+day)[[:space:]]+at[[:space:]]+([0-9]{1,2})(:[0-9]{2})?(am|pm)? ]]; then
        local hour="${BASH_REMATCH[2]}"
        local minute="${BASH_REMATCH[3]:-:00}"
        local ampm="${BASH_REMATCH[4]}"
        minute="${minute#:}"
        
        # Convert to 24h if needed
        if [[ "$ampm" == "pm" ]] && [[ $hour -lt 12 ]]; then
            hour=$((hour + 12))
        elif [[ "$ampm" == "am" ]] && [[ $hour -eq 12 ]]; then
            hour=0
        fi
        
        # Cron: minute hour * * *
        echo "cron:$minute $hour * * *"
        return
    fi
    
    # Weekday at time (e.g., "every Monday at 2pm")
    if [[ "$input" =~ every[[:space:]]+(Monday|Tuesday|Wednesday|Thursday|Friday|Saturday|Sunday)[[:space:]]+at[[:space:]]+([0-9]{1,2})(:[0-9]{2})?(am|pm)? ]]; then
        local day="${BASH_REMATCH[1]}"
        local hour="${BASH_REMATCH[2]}"
        local minute="${BASH_REMATCH[3]:-:00}"
        local ampm="${BASH_REMATCH[4]}"
        minute="${minute#:}"
        
        # Convert to 24h if needed
        if [[ "$ampm" == "pm" ]] && [[ $hour -lt 12 ]]; then
            hour=$((hour + 12))
        elif [[ "$ampm" == "am" ]] && [[ $hour -eq 12 ]]; then
            hour=0
        fi
        
        # Convert day to cron day-of-week (0=Sunday)
        local dow
        case "$day" in
            Sunday) dow=0 ;;
            Monday) dow=1 ;;
            Tuesday) dow=2 ;;
            Wednesday) dow=3 ;;
            Thursday) dow=4 ;;
            Friday) dow=5 ;;
            Saturday) dow=6 ;;
        esac
        
        # Cron: minute hour * * day-of-week
        echo "cron:$minute $hour * * $dow"
        return
    fi
    
    # Weekly (defaults to Monday 9am)
    if [[ "$input" =~ ^weekly$ ]]; then
        echo "cron:0 9 * * 1"
        return
    fi
    
    echo "error"
}

# Parse the schedule
PARSED=$(parse_schedule "$SCHEDULE")
if [[ "$PARSED" == "error" ]]; then
    echo "Error: Could not parse schedule: $SCHEDULE"
    exit 1
fi

# Build cron command based on type
if [[ "$PARSED" =~ ^duration:(.+)$ ]]; then
    DURATION="${BASH_REMATCH[1]}"
    cd /home/julian/clawdbot
    JOB_OUTPUT=$(npx tsx src/index.ts cron add \
        --name "Recurring: $MESSAGE" \
        --every "$DURATION" \
        --session isolated \
        --wake now \
        --message "⏰ $MESSAGE" \
        --deliver \
        --channel telegram \
        --to 6636746252 \
        --json 2>&1)
    SCHEDULE_DISPLAY="every $DURATION"
elif [[ "$PARSED" =~ ^cron:(.+)$ ]]; then
    CRON_EXPR="${BASH_REMATCH[1]}"
    cd /home/julian/clawdbot
    JOB_OUTPUT=$(npx tsx src/index.ts cron add \
        --name "Recurring: $MESSAGE" \
        --cron "$CRON_EXPR" \
        --tz "$TIMEZONE" \
        --session isolated \
        --wake now \
        --message "⏰ $MESSAGE" \
        --deliver \
        --channel telegram \
        --to 6636746252 \
        --json 2>&1)
    SCHEDULE_DISPLAY="cron: $CRON_EXPR"
fi

if [[ $? -ne 0 ]]; then
    echo "Error creating cron job: $JOB_OUTPUT"
    exit 1
fi

# Extract JSON from output
JSON_OUTPUT=$(echo "$JOB_OUTPUT" | grep -A100 "^{" | grep -B100 "^}")
JOB_ID=$(echo "$JSON_OUTPUT" | jq -r '.id' 2>/dev/null)

# Log to markdown
mkdir -p "$(dirname "$REMINDERS_FILE")"
echo "- [recurring] $SCHEDULE_DISPLAY | $MESSAGE (id: $JOB_ID)" >> "$REMINDERS_FILE"

echo "✅ Recurring reminder set: $SCHEDULE_DISPLAY"
echo "📝 Logged to $REMINDERS_FILE"
echo "🆔 Job ID: $JOB_ID"


path: create-reminder.sh
content: #!/bin/bash
# Create a one-time reminder
# Usage: create-reminder.sh "message" "when"

MESSAGE="$1"
WHEN="$2"
REMINDERS_FILE="/home/julian/clawd/reminders.md"
TIMEZONE="Europe/Warsaw"

[[ -z "$MESSAGE" ]] && echo "Error: No message provided" && exit 1
[[ -z "$WHEN" ]] && echo "Error: No time provided" && exit 1

# Parse natural language to timestamp
parse_time() {
    local input="$1"
    local now=$(date +%s)
    
    # Relative times with "in X minutes/hours/days"
    if [[ "$input" =~ in[[:space:]]+([0-9]+)[[:space:]]+(minute|hour|day)s? ]]; then
        local amount="${BASH_REMATCH[1]}"
        local unit="${BASH_REMATCH[2]}"
        case "$unit" in
            minute) date -d "+${amount} minutes" --iso-8601=seconds ;;
            hour) date -d "+${amount} hours" --iso-8601=seconds ;;
            day) date -d "+${amount} days" --iso-8601=seconds ;;
        esac
        return
    fi
    
    # Time of day shortcuts
    case "$input" in
        "later today"|"later"|"this afternoon")
            date -d "today 17:00" --iso-8601=seconds
            return
            ;;
        "tonight")
            date -d "today 20:00" --iso-8601=seconds
            return
            ;;
        "tomorrow")
            date -d "tomorrow 09:00" --iso-8601=seconds
            return
            ;;
    esac
    
    # Try GNU date parsing
    date -d "$input" --iso-8601=seconds 2>/dev/null
}

# Parse the time
TIMESTAMP=$(parse_time "$WHEN")
if [[ -z "$TIMESTAMP" ]]; then
    echo "Error: Could not parse time: $WHEN"
    exit 1
fi

# Format for display
DISPLAY_TIME=$(date -d "$TIMESTAMP" '+%Y-%m-%d %H:%M')

# Create cron job
cd /home/julian/clawdbot
JOB_OUTPUT=$(npx tsx src/index.ts cron add \
    --name "Reminder: $MESSAGE" \
    --at "$TIMESTAMP" \
    --session isolated \
    --wake now \
    --message "⏰ Reminder: $MESSAGE" \
    --deliver \
    --channel telegram \
    --to 6636746252 \
    --json 2>&1)

if [[ $? -ne 0 ]]; then
    echo "Error creating cron job: $JOB_OUTPUT"
    exit 1
fi

# Extract JSON from output (skip npm warnings)
JSON_OUTPUT=$(echo "$JOB_OUTPUT" | grep -A100 "^{" | grep -B100 "^}")
JOB_ID=$(echo "$JSON_OUTPUT" | jq -r '.id' 2>/dev/null)

# Log to markdown
mkdir -p "$(dirname "$REMINDERS_FILE")"
echo "- [scheduled] $DISPLAY_TIME | $MESSAGE (id: $JOB_ID)" >> "$REMINDERS_FILE"

echo "✅ Reminder set for $DISPLAY_TIME"
echo "📝 Logged to $REMINDERS_FILE"
echo "🆔 Job ID: $JOB_ID"


Security scan verdicts — ClawScan: malicious | static analysis: clean | VirusTotal: suspicious | SkillSpector:  ()