5 Miru CLI Workflows That Save Our Team Hours Every Week
Real shell scripts and automation patterns our team uses daily. Git hooks, cron invoicing, Slack integration, and more.
The Miru CLI isn’t just a command-line interface. It’s an automation surface. Every command is composable, every output is parseable, and everything can run unattended. Here are five real workflows our team at Saeloun uses every day. All of them are copy-pasteable. None of them require a browser.
1. Git Post-Commit Hook: Log Time When You Commit
This is the one that captures hours that would otherwise vanish. Every time you commit, the hook asks if you want to log time. The commit message becomes the time entry description automatically.
#!/bin/bash
# Save as .git/hooks/post-commit and chmod +x
COMMIT_MSG=$(git log -1 --pretty=%s)
PROJECT=$(basename "$(git rev-parse --show-toplevel)")
BRANCH=$(git branch --show-current)
echo ""
echo "--- Miru Time Logger ---"
echo "Project: $PROJECT ($BRANCH)"
echo "Commit: $COMMIT_MSG"
echo ""
read -p "Hours spent (or 'skip'): " DURATION
if [ "$DURATION" != "skip" ] && [ -n "$DURATION" ]; then
miru time create \
--project "$PROJECT" \
--duration "${DURATION}h" \
--date today \
--note "$COMMIT_MSG"
echo "Logged ${DURATION}h to $PROJECT"
fi
The project name is pulled from the repo directory name. Match your Miru project names to your repo names and this is zero-config. The branch name is displayed so you know which feature you were on. You type a number and move on.
Our team captures an extra 3-5 hours per week per developer with this hook. That’s billable time that used to disappear into the void.
2. Monday Morning Invoice Generator
First of the month. Time to bill. This cron job generates and sends invoices for all clients with uninvoiced time.
#!/bin/bash
# miru-monthly-invoicing.sh
# Cron: 0 9 1 * * /opt/scripts/miru-monthly-invoicing.sh
LAST_MONTH_START=$(date -d "last month" +%Y-%m-01)
LAST_MONTH_END=$(date -d "$(date +%Y-%m-01) - 1 day" +%Y-%m-%d)
echo "Generating invoices for $LAST_MONTH_START to $LAST_MONTH_END"
# Get all clients with unbilled time entries
miru client list --format json | jq -r '.[].name' | while read CLIENT; do
HOURS=$(miru time list \
--client "$CLIENT" \
--from "$LAST_MONTH_START" \
--to "$LAST_MONTH_END" \
--status unbilled \
--format json | jq '[.[].duration] | add // 0')
if [ "$HOURS" != "0" ] && [ "$HOURS" != "null" ]; then
echo "Creating invoice for $CLIENT: ${HOURS}h"
INVOICE_ID=$(miru invoice create \
--client "$CLIENT" \
--from "$LAST_MONTH_START" \
--to "$LAST_MONTH_END" \
--format json | jq -r '.id')
echo "Created invoice #$INVOICE_ID for $CLIENT"
fi
done
echo "Done. Review drafts: miru invoice list --status draft"
Add to cron:
crontab -e
# 0 9 1 * * /opt/scripts/miru-monthly-invoicing.sh >> /var/log/miru-invoicing.log 2>&1
The script creates draft invoices. It does not send them automatically. You review the drafts, make any adjustments, and send with one command per invoice. Automation handles the tedious part. A human handles the judgment call.
3. Weekly Time Report to Slack
Every Friday at 4 PM, a summary of the team’s hours lands in Slack. No one has to pull a report manually.
#!/bin/bash
# miru-slack-weekly.sh
# Cron: 0 16 * * 5 /opt/scripts/miru-slack-weekly.sh
MONDAY=$(date -d "last monday" +%Y-%m-%d)
FRIDAY=$(date +%Y-%m-%d)
SLACK_WEBHOOK="https://hooks.slack.com/services/YOUR/WEBHOOK/URL"
REPORT=$(miru report time --from "$MONDAY" --to "$FRIDAY" --format text)
TOTAL=$(miru time list --from "$MONDAY" --to "$FRIDAY" --format json | \
jq '[.[].duration] | add | . * 100 | round / 100')
PAYLOAD=$(cat <<EOF
{
"blocks": [
{
"type": "header",
"text": {
"type": "plain_text",
"text": "Weekly Time Report: $MONDAY to $FRIDAY"
}
},
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": "*Total Hours:* ${TOTAL}h\n\n\`\`\`\n${REPORT}\n\`\`\`"
}
}
]
}
EOF
)
curl -s -X POST -H 'Content-type: application/json' \
--data "$PAYLOAD" "$SLACK_WEBHOOK"
Set up a Slack incoming webhook, paste the URL, add to cron. The team sees hours logged per project, per person. It takes 30 seconds to scan. If someone’s hours look off, you catch it on Friday instead of discovering it during month-end invoicing.
4. End-of-Day Unlogged Commit Checker
This script compares your git commits with your Miru time entries and tells you what you forgot to log. Run it before closing your laptop.
#!/bin/bash
# miru-unlogged-check.sh
echo "=== Unlogged Work Detector ==="
echo "Checking commits from today against Miru entries..."
echo ""
LOGGED_HOURS=$(miru time list --from today --to today --format json | \
jq '[.[].duration] | add // 0')
echo "Total logged today: ${LOGGED_HOURS}h"
echo ""
echo "Commits made today:"
for REPO_DIR in ~/code/*/; do
if [ -d "$REPO_DIR/.git" ]; then
REPO_NAME=$(basename "$REPO_DIR")
COMMITS=$(git -C "$REPO_DIR" log --since=midnight --oneline --author="$(git config user.email)" 2>/dev/null)
if [ -n "$COMMITS" ]; then
echo ""
echo " $REPO_NAME:"
echo "$COMMITS" | while read LINE; do
echo " $LINE"
done
fi
fi
done
echo ""
if (( $(echo "$LOGGED_HOURS < 4" | bc -l) )); then
echo "WARNING: Less than 4 hours logged today. Missing something?"
else
echo "Looks good. ${LOGGED_HOURS}h logged."
fi
The script scans every repo in your code directory, finds today’s commits, and compares them against your logged hours. If you committed to three repos but only logged time on one, you’ll see it. If you logged under 4 hours on a full workday, it flags it.
This is a safety net, not a surveillance tool. Run it yourself, on your own machine. It never reports to anyone but you.
5. Expense Receipt Logger from the Terminal
Conference trip. Client dinner. Software subscription. Log the expense without opening a browser:
#!/bin/bash
# miru-expense.sh - Quick expense logging
echo "--- Quick Expense Logger ---"
read -p "Amount: $" AMOUNT
read -p "Category (software/travel/meals/equipment/other): " CATEGORY
read -p "Vendor: " VENDOR
read -p "Note: " NOTE
read -p "Receipt file path (or 'none'): " RECEIPT
CMD="miru expense create --amount $AMOUNT --category $CATEGORY --vendor \"$VENDOR\" --date today --note \"$NOTE\""
if [ "$RECEIPT" != "none" ] && [ -f "$RECEIPT" ]; then
CMD="$CMD --receipt $RECEIPT"
fi
eval $CMD
echo ""
echo "Expense logged: \$$AMOUNT to $CATEGORY ($VENDOR)"
Save it as miru-expense.sh in your path. When you get back from lunch with a client:
miru-expense.sh
# Amount: $47.50
# Category: meals
# Vendor: Blue Bottle Coffee
# Note: Client lunch with Acme team
# Receipt file path: ~/Downloads/receipt-20260313.jpg
#
# Expense logged: $47.50 to meals (Blue Bottle Coffee)
The receipt photo attaches to the expense entry. Your bookkeeper sees the entry, the amount, the category, and the photo. No email forwarding. No scanning apps. No “I’ll do it later” that becomes “I forgot.”
The Compound Effect
None of these scripts is revolutionary. A git hook. A cron job. A Slack webhook. A shell script. Basic tools that have been around for decades.
But the compound effect is real. The git hook catches 3-5 hours per week. The cron invoicing saves half a day per month. The Slack report catches discrepancies before they become billing disputes. The unlogged checker closes the gap at the end of each day. The expense logger eliminates the “I lost the receipt” problem.
Stack all five together and you’re looking at 10-15 hours per month per team member that used to be wasted on admin overhead or lost to poor tracking. For a 10-person team billing at $100/hour, that’s $10,000-15,000/month in recovered productivity and captured revenue.
Install the CLI. Pick one workflow. Add it today.
curl -fsSL https://miru.so/install.sh | sh
Start with the git hook. Everything else can wait until next week.
Vipul A M
Co-founder at Saeloun. Building Miru. Rails contributor. Shipping from Pune, India.
Read next
How We Track Time with AI Agents and the Miru CLI
A practical guide to automated time tracking for teams using Claude Code, Codex, and other AI coding tools. Real workflows, real scripts, zero browser tabs.
Why We Built the Miru CLI (And Why Every SaaS Should Have One)
Most SaaS tools treat the terminal as an afterthought. We built a full CLI because developers deserve better than a browser tab.