Every developer has tasks they repeat daily. Setting up a local environment, running test suites, deploying to staging, cleaning up old branches, generating boilerplate. These tasks eat up time not because they are hard, but because they are frequent. The fix is almost always a shell script.
I spent a week tracking every terminal command I ran more than twice a day. The results were embarrassing. I was typing the same sequences of 4-5 commands dozens of times per week. That is when I started building a personal automation toolkit.
The Three-Minute Rule
If a task takes less than three minutes to do manually, most developers never bother automating it. That is a mistake. Three minutes done ten times a week is 30 minutes. Over a year, that is 26 hours - more than three full working days spent on a single repetitive task.
The rule I follow now: if I do something more than three times, I write a script for it. The script does not need to be perfect. It just needs to work.
Start With a Project Setup Script
The most impactful script I wrote was a project bootstrapper. Every time I started a new microservice, I was manually creating directories, copying config files, initializing git, setting up a Makefile, and configuring the CI pipeline. This took about 15 minutes each time.
#!/bin/bash
# new-service.sh - Bootstrap a new microservice
SERVICE_NAME=$1
if [ -z "$SERVICE_NAME" ]; then
echo "Usage: new-service.sh "
exit 1
fi
mkdir -p "$SERVICE_NAME"/{cmd,internal,pkg,configs,scripts}
cd "$SERVICE_NAME"
git init
cp ~/.templates/Makefile .
cp ~/.templates/.gitignore .
cp ~/.templates/Dockerfile .
cp ~/.templates/.github/workflows/ci.yml .github/workflows/
sed -i "s/SERVICE_NAME/$SERVICE_NAME/g" Makefile
go mod init "github.com/myorg/$SERVICE_NAME"
echo "Service $SERVICE_NAME created."
Fifteen minutes became five seconds. More importantly, every service now has a consistent structure, which makes onboarding and debugging much easier.
Git Cleanup Scripts
Another high-value target: git branch cleanup. After a few months on an active project, you accumulate dozens of stale local branches that have already been merged. Cleaning them manually is tedious.
#!/bin/bash
# clean-branches.sh - Remove merged local branches
git fetch --prune
BRANCHES=$(git branch --merged main | grep -v "main" | grep -v "\*")
if [ -z "$BRANCHES" ]; then
echo "No merged branches to clean."
exit 0
fi
echo "Removing merged branches:"
echo "$BRANCHES"
echo "$BRANCHES" | xargs git branch -d
I run this weekly. It keeps my local repo clean without any thought.
Log Watching and Alerts
When debugging services locally, I used to manually tail logs and scan for errors with my eyes. A simple wrapper script changed that completely.
#!/bin/bash
# watch-errors.sh - Tail logs and highlight errors
LOG_FILE=${1:-/var/log/app.log}
tail -f "$LOG_FILE" | while read LINE; do
if echo "$LINE" | grep -qi "error\|panic\|fatal"; then
echo -e "\033[31m$LINE\033[0m"
else
echo "$LINE"
fi
done
Errors show up in red. No more scanning through walls of text. It is a tiny quality-of-life improvement, but it adds up over long debugging sessions.
Database Seeding
Setting up a local development database with test data was another recurring task. Instead of running SQL commands manually or clicking through a UI, I wrote a single script that drops the database, recreates it, runs migrations, and seeds test data. One command, and I have a clean development environment.
Making Scripts Discoverable
The biggest lesson I learned is that scripts you forget about are scripts you do not use. I keep all my personal automation in a single directory (~/scripts) which is added to my PATH. Each script has a consistent naming pattern and a help flag. I also keep a simple text file listing what each script does.
For project-specific scripts, I use a scripts/ directory at the root of the repo. This way, every team member benefits from the automation, and the scripts are version-controlled alongside the code they support.
The Compound Effect
None of these scripts are impressive on their own. Each one saves a few minutes. But collectively, they save hours per week and - more importantly - they reduce context switching. When a task is automated, you do not have to remember the exact sequence of steps. You do not have to worry about missing a step. You just run the script and move on to the actual problem you are trying to solve.
Start small. Pick the one task you did three times today and write a script for it tonight. You will thank yourself by Friday.