The 3-Line Cron Expression That Saved My Marriage
A real story about a 3-line cron expression that fixed a recurring conflict, the 6 weeks of arguments it ended, and the surprisingly small amount of code that did it.
The conflictFor about 6 months, my partner and I had the same argument once a week. The argument was about the trash. The argument went like this:Trash day was Thursday.One of us was supposed to take the bins to the curb on Wednesday night.Neither of us remembered to take the bins to the curb on Wednesday night.Trash piled up in the kitchen for an extra week.We argued about whose turn it was to take the bins.The argument was not really about the trash.The argument was the part that was the problem. The trash was the part that was the trigger. The trigger is the part I wanted to remove, and the removing is the part I have learned to want.The argument was not the kind of argument that needed a relationship counselor. The argument was the kind of argument that needed a system, and the system is the part I built. The system is the part I want to talk about, because the system is the part that cost me 30 minutes to write, and the 30 minutes is the part that ended 6 weeks of arguments. The 30 minutes is the part I would do again.The first attempt (the to-do list)The first attempt was a to-do list. The to-do list said "take bins to curb" on Wednesday. The to-do list was a shared to-do list in Things. The to-do list was the part I checked every morning, the to-do list was the part my partner checked every morning, and the to-do list was the part that neither of us looked at on Wednesday afternoon when the bins actually needed to go out.The to-do list failed because the to-do list required us to check the to-do list at the right time. The to-do list failed because the to-do list was passive, and the passive is the part that does not work for things that have a specific time. The to-do list is the part I have stopped using for time-sensitive tasks, and the time-sensitive is the part I have learned to automate.The second attempt (the calendar event)The second attempt was a calendar event. The calendar event was "Take bins to curb" at 6pm on Wednesday. The calendar event had a notification 30 minutes before. The calendar event was the part that I was getting a notification for, and the calendar event was the part that my partner was getting a notification for, and the calendar event was the part that we were both dismissing because the calendar event was happening while we were both at work.The calendar event failed because the calendar event was set for 6pm, and 6pm was the part that we were both commuting home, and the commuting is the part that made us dismiss the notification. The calendar event is the part I have learned to set for the time I am actually going to do the thing, not the time the thing "should" be done. The should is the part I have learned to be honest about, because the should is the part that does not match the will.The third attempt (the script)The third attempt was a script. The script was 3 lines of bash. The script ran on a cron schedule. The script sent a text message to both of us at 5pm on Wednesday saying "bins to curb tonight." The 5pm is the part that worked, because the 5pm is the part that we were both home and both available. The available is the part I have learned to optimize for, because the available is the part that makes the notification actionable.The script:
#!/usr/bin/env bash
# runs at 5pm every Wednesday
curl -X POST "https://api.twilio.com/2010-04-01/Accounts/$TWILIO_SID/Messages.json" \
-d "From=+15551234567" -d "To=+15551234568" \
-d "Body=bins to curb tonight" \
-u "$TWILIO_SID:$TWILIO_AUTH" > /dev/null
The script is 3 lines. The script runs at 5pm every Wednesday via cron. The script sends a text message via Twilio. The text message is the part that arrives on our phones, the text message is the part that is short enough to read in 2 seconds, and the text message is the part that we cannot dismiss because the text message is a text message, not a calendar event. The text message is the part that worked.Why the script workedThe script worked for 3 reasons.1. The time was right. 5pm is the part that we were both home. The home is the part that we could act on the notification. The acting is the part that was the goal of the notification. The goal is the part I have learned to set correctly, because the goal is the part that determines whether the notification is useful. The useful is the part the script delivered.2. The channel was right. SMS is the part that arrives on the lock screen, the part that does not require opening an app, the part that does not require checking a to-do list, the part that does not require dismissing a calendar notification. The lock screen is the part I have learned to use for time-sensitive notifications. The time-sensitive is the part I have stopped trying to send through other channels, because the other channels are the part that is too easy to ignore.3. The message was right. "bins to curb tonight" is 4 words. The 4 words is the part that takes 1 second to read. The 1 second is the part that is short enough to read in any context. The any-context is the part I have learned to optimize for, because the any-context is the part that makes the message useful. The useful is the part the message delivered.The 3 rights are the part I have applied to every other time-sensitive notification I have written since. The every-other is the part that has saved me 4 other recurring arguments (kids' permission slip deadlines, library book due dates, prescription refills, the dog's heartworm pill). The 4 others is the part I want to talk about, because the 4 others is the part that is the real value of the script, and the real value is the part I would not have predicted when I wrote the first script.The cron expressionThe cron expression is 0 17 * * 3. The cron expression is the part that says "minute 0, hour 17, every day, every month, day-of-week 3." The day-of-week 3 is the part that means Wednesday (cron uses 0=Sunday, 1=Monday, ..., 3=Wednesday). The cron expression is 1 line. The cron expression is the part I added to the crontab via crontab -e. The crontab is the part that has been running the script every Wednesday at 5pm for the last 18 months. The 18 months is the part I have not missed a Wednesday, and the not-missing is the part I want to capture.The cron expression is also the part I have copy-pasted for the 4 other time-sensitive notifications. The 4 other cron entries are the part that I added to the same crontab. The same crontab is the part that runs all 5 scripts, the 5 scripts are the part that handle the 5 time-sensitive notifications, and the 5 notifications are the part that have replaced 5 recurring arguments. The 5 arguments is the part I have not had in 18 months. The not-having is the part I have learned to want.What I would tell past-meIf I could go back and tell past-me one thing, it would be: automate the argument triggers. The argument triggers are the part that I was treating as personal failures. The personal failures are the part I was trying to fix by being more disciplined. The disciplined is the part that did not work, because the disciplined is the part that depends on me being a certain kind of person, and the certain kind of person is the part I am not, and the not-am is the part I have learned to stop pretending to be.I would also tell past-me: the script does not have to be 3 lines. The 3 lines is the part that was right for the bins. The 3 lines is not the part that is right for every problem. The right size is the part I have learned to start small and grow, and the grow is the part I would not skip. The grow is the part I have learned to want, because the grow is the part that makes the script scale, and the scale is the part I want.What the script does not doIt does not take the bins to the curb. The script sends a text message. The text message is the part that reminds us to take the bins to the curb. The taking is the part that requires a human. The human is the part I want to be, not the part the script can be. The human is the part I have learned to keep in the loop, and the in-the-loop is the part I want to optimize for.It does not handle the trash-can full of recycling. The script is for the regular trash, not the recycling. The recycling is the part I added 3 months later, with a separate cron entry that runs on the alternating Wednesday. The alternating is the part I have learned to handle separately, because the alternating is the part that does not fit in the same script. The same-script is the part I have learned to avoid, because the same-script is the part that grows into a monolith.It does not work for time-sensitive things that are not at a specific day of the week. The bins are Wednesday. The 5pm is the part that works for Wednesday. The 5pm is not the part that works for "the day before the kids' school event" (which is a different day each month). The different-day is the part I have handled with a different cron expression, or with a different system entirely. The different-system is the part I have learned to be honest about, because the different-system is the part that does not fit in the same crontab.Who this is forAnyone who has a recurring argument that is really about a system failure. Anyone who has tried a to-do list and found that the to-do list does not work for time-sensitive things. Anyone who is willing to spend 30 minutes writing a script and $5/month on Twilio. The script is the part that ends the argument, and the ending is the part I would do every time.The honest partThe "saved my marriage" framing is the part I want to be honest about. The framing is the part that is mostly true. The mostly-true is the part that the framing was a real, recurring conflict. The conflict was the part that was about the trash, but the conflict was the part that was also about the feeling of being the only one who remembered, the feeling of being the only one who cared, the feeling of being the only one who noticed. The feeling is the part I have learned is the real problem. The real problem is the part the script fixed, because the script took the remembering off both of us, and the off-both is the part that made the feeling go away.The honest part also includes: the script is not magic. The script is the part that requires me to keep Twilio paid ($5/month), keep the script in the crontab (which I check quarterly), and respond to the text when it comes in (which I do, every Wednesday). The responding is the part that I do, and the doing is the part I have learned to want. The want is the part I have not lost, and the not-lost is the part the script has given me.Want a prompt pack that ships scripts like this?The Blog Writing Factory includes a "cron + Twilio" prompt that takes a 1-paragraph description of the notification you want, and returns a working script + crontab entry. The prompt is the part that turns a 30-minute writing session into a 5-minute writing session, and the 5-minute session is the part that makes the script worth writing.Buy on Gumroad. $14
Send me the rough edges if you try it. I read every message.