Skip to content
Miru 3.0 is here — expenses, CLI, dark mode, and 6 report types. Read the announcement →
CLI Workflows

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.

Vipul A M · · 5 min read

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.

Share:
VA

Vipul A M

Co-founder at Saeloun. Building Miru. Rails contributor. Shipping from Pune, India.

Try Miru today

Free to start. No credit card required.

Start Tracking Free