DEV Community

Otto
Otto

Posted on

5 Python Scripts to Automate Your Freelance Business (No Libraries Needed)

Python is the perfect tool for automating boring freelance tasks. Here are 5 scripts you can actually use today — no complex libraries needed.

Why Automate Your Freelance Business?

Every hour you spend on admin (invoicing, tracking, reporting) is an hour you're not billing. These scripts won't replace your work — they'll free you up to do more of it.

All scripts use only Python's standard library. No pip install needed.


Script 1: Automated Time Tracker

Track exactly where your hours go with a simple CLI tool.

#!/usr/bin/env python3
"""time_tracker.py - Simple CLI time tracker"""
import json
import time
import sys
from datetime import datetime
from pathlib import Path

DATA_FILE = Path.home() / ".time_tracker.json"

def load_data():
    if DATA_FILE.exists():
        return json.loads(DATA_FILE.read_text())
    return {"sessions": []}

def save_data(data):
    DATA_FILE.write_text(json.dumps(data, indent=2))

def start_session(project: str):
    data = load_data()
    session = {
        "project": project,
        "start": datetime.now().isoformat(),
        "end": None,
        "duration_mins": None
    }
    data["sessions"].append(session)
    save_data(data)
    print(f"⏱ Started tracking: {project}")
    print("Press Ctrl+C to stop...")

    start_time = time.time()
    try:
        while True:
            elapsed = int(time.time() - start_time)
            hours, mins = divmod(elapsed // 60, 60)
            print(f"\r  Elapsed: {hours:02d}h{mins:02d}m", end="", flush=True)
            time.sleep(10)
    except KeyboardInterrupt:
        end_time = datetime.now()
        duration_mins = int((time.time() - start_time) / 60)
        session["end"] = end_time.isoformat()
        session["duration_mins"] = duration_mins
        save_data(data)
        print(f"\n✅ Logged {duration_mins} minutes for {project}")

def report():
    data = load_data()
    totals = {}
    for s in data["sessions"]:
        if s["duration_mins"]:
            totals[s["project"]] = totals.get(s["project"], 0) + s["duration_mins"]

    print("\n📊 Time Report")
    print("-" * 40)
    for project, mins in sorted(totals.items(), key=lambda x: -x[1]):
        hours, m = divmod(mins, 60)
        print(f"  {project}: {hours}h{m:02d}m")
    print(f"\n  Total: {sum(totals.values())//60}h{sum(totals.values())%60:02d}m")

if __name__ == "__main__":
    if len(sys.argv) < 2:
        print("Usage: python time_tracker.py start <project> | report")
    elif sys.argv[1] == "start" and len(sys.argv) > 2:
        start_session(" ".join(sys.argv[2:]))
    elif sys.argv[1] == "report":
        report()
Enter fullscreen mode Exit fullscreen mode

Usage:

python time_tracker.py start "Client A - Homepage redesign"
python time_tracker.py report
Enter fullscreen mode Exit fullscreen mode

Script 2: Invoice Number Generator

Never manually track invoice numbers again.

#!/usr/bin/env python3
"""invoice_numbering.py - Auto-increment invoice numbers"""
import json
from pathlib import Path
from datetime import datetime

COUNTER_FILE = Path.home() / ".invoice_counter.json"

def get_next_invoice_number(prefix="INV"):
    data = {"counter": 0}
    if COUNTER_FILE.exists():
        data = json.loads(COUNTER_FILE.read_text())

    data["counter"] += 1
    COUNTER_FILE.write_text(json.dumps(data))

    year = datetime.now().year
    num = str(data["counter"]).zfill(3)
    invoice_number = f"{prefix}-{year}-{num}"

    print(f"✅ Next invoice number: {invoice_number}")
    return invoice_number

if __name__ == "__main__":
    get_next_invoice_number()
Enter fullscreen mode Exit fullscreen mode

Output:

✅ Next invoice number: INV-2026-001
Enter fullscreen mode Exit fullscreen mode

Script 3: Client Communication Logger

Log all client interactions for reference (and disputes).

#!/usr/bin/env python3
"""client_log.py - Log client interactions"""
import json
import sys
from datetime import datetime
from pathlib import Path

LOG_FILE = Path("client_log.json")

def add_entry(client: str, type: str, notes: str):
    data = []
    if LOG_FILE.exists():
        data = json.loads(LOG_FILE.read_text())

    entry = {
        "date": datetime.now().isoformat(),
        "client": client,
        "type": type,  # email, call, meeting, revision_request
        "notes": notes
    }
    data.append(entry)
    LOG_FILE.write_text(json.dumps(data, indent=2))
    print(f"✅ Logged: [{type}] {client}")

def show_client(client: str):
    if not LOG_FILE.exists():
        print("No log found")
        return

    data = json.loads(LOG_FILE.read_text())
    entries = [e for e in data if client.lower() in e["client"].lower()]

    print(f"\n📋 Log for: {client}")
    print("-" * 50)
    for e in sorted(entries, key=lambda x: x["date"], reverse=True):
        date = e["date"][:10]
        print(f"  {date} [{e['type']}] {e['notes'][:80]}")

if __name__ == "__main__":
    if sys.argv[1] == "add":
        add_entry(sys.argv[2], sys.argv[3], " ".join(sys.argv[4:]))
    elif sys.argv[1] == "show":
        show_client(sys.argv[2])
Enter fullscreen mode Exit fullscreen mode

Usage:

python client_log.py add "Acme Corp" call "Discussed Q2 deliverables, 3 revisions allowed"
python client_log.py show "Acme Corp"
Enter fullscreen mode Exit fullscreen mode

Script 4: Weekly Revenue Calculator

Calculate your weekly/monthly revenue at a glance.

#!/usr/bin/env python3
"""revenue_calc.py - Weekly revenue summary"""
import json
from datetime import datetime, timedelta
from pathlib import Path

EARNINGS_FILE = Path("earnings.json")

def log_payment(client: str, amount: float, description: str = ""):
    data = []
    if EARNINGS_FILE.exists():
        data = json.loads(EARNINGS_FILE.read_text())

    data.append({
        "date": datetime.now().isoformat()[:10],
        "client": client,
        "amount": amount,
        "description": description
    })
    EARNINGS_FILE.write_text(json.dumps(data, indent=2))
    print(f"✅ Logged €{amount:.2f} from {client}")

def weekly_summary():
    if not EARNINGS_FILE.exists():
        print("No earnings logged yet")
        return

    data = json.loads(EARNINGS_FILE.read_text())
    today = datetime.now().date()
    week_ago = today - timedelta(days=7)
    month_ago = today - timedelta(days=30)

    weekly = sum(e["amount"] for e in data 
                 if datetime.fromisoformat(e["date"]).date() >= week_ago)
    monthly = sum(e["amount"] for e in data 
                  if datetime.fromisoformat(e["date"]).date() >= month_ago)
    total = sum(e["amount"] for e in data)

    print(f"\n💰 Revenue Summary")
    print(f"  This week: €{weekly:.2f}")
    print(f"  This month: €{monthly:.2f}")
    print(f"  All time: €{total:.2f}")

    # Top clients
    clients = {}
    for e in data:
        clients[e["client"]] = clients.get(e["client"], 0) + e["amount"]

    print(f"\n  Top clients:")
    for client, amount in sorted(clients.items(), key=lambda x: -x[1])[:5]:
        print(f"    {client}: €{amount:.2f}")

import sys
if __name__ == "__main__":
    if len(sys.argv) > 1 and sys.argv[1] == "add":
        log_payment(sys.argv[2], float(sys.argv[3]), " ".join(sys.argv[4:]))
    else:
        weekly_summary()
Enter fullscreen mode Exit fullscreen mode

Script 5: Project Deadline Tracker

Get reminders for upcoming deadlines.

#!/usr/bin/env python3
"""deadlines.py - Track project deadlines"""
import json
import sys
from datetime import datetime, date
from pathlib import Path

DEADLINES_FILE = Path("deadlines.json")

def add_deadline(project: str, deadline: str, client: str = ""):
    data = []
    if DEADLINES_FILE.exists():
        data = json.loads(DEADLINES_FILE.read_text())

    data.append({
        "project": project,
        "deadline": deadline,
        "client": client,
        "done": False
    })
    DEADLINES_FILE.write_text(json.dumps(data, indent=2))
    print(f"✅ Added deadline: {project}{deadline}")

def check_deadlines():
    if not DEADLINES_FILE.exists():
        print("No deadlines tracked")
        return

    data = json.loads(DEADLINES_FILE.read_text())
    today = date.today()

    upcoming = [d for d in data if not d["done"]]
    upcoming.sort(key=lambda x: x["deadline"])

    print(f"\n📅 Upcoming Deadlines")
    print("-" * 50)
    for d in upcoming:
        deadline_date = datetime.strptime(d["deadline"], "%Y-%m-%d").date()
        days_left = (deadline_date - today).days

        if days_left < 0:
            icon = "🔴"
            status = f"OVERDUE by {abs(days_left)} days"
        elif days_left == 0:
            icon = "🔴"
            status = "DUE TODAY"
        elif days_left <= 3:
            icon = "🟡"
            status = f"{days_left} days left"
        else:
            icon = "🟢"
            status = f"{days_left} days left"

        client_str = f" [{d['client']}]" if d['client'] else ""
        print(f"  {icon} {d['project']}{client_str}: {status}")

if __name__ == "__main__":
    if len(sys.argv) > 1 and sys.argv[1] == "add":
        client = sys.argv[4] if len(sys.argv) > 4 else ""
        add_deadline(sys.argv[2], sys.argv[3], client)
    else:
        check_deadlines()
Enter fullscreen mode Exit fullscreen mode

Usage:

python deadlines.py add "Homepage Redesign" "2026-03-30" "Acme Corp"
python deadlines.py
Enter fullscreen mode Exit fullscreen mode

Output:

📅 Upcoming Deadlines
--------------------------------------------------
  🟡 Homepage Redesign [Acme Corp]: 7 days left
  🟢 Mobile App v2 [TechStart]: 14 days left
Enter fullscreen mode Exit fullscreen mode

Put It All Together

These 5 scripts cover:

  • Time tracking → know your real hourly rate
  • Invoice numbering → professional, consistent billing
  • Client logging → never lose context
  • Revenue tracking → know your numbers
  • Deadline management → never miss a delivery

Total setup time: 30 minutes. Time saved per week: 2-4 hours.


Want to take your freelance business to the next level? The Invoice Generator Pro gives you a complete invoicing solution — client management, VAT calculation, PDF export, all in Python. And the Freelancer OS Notion Template keeps your entire business organized in one place.

Top comments (0)