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()
Usage:
python time_tracker.py start "Client A - Homepage redesign"
python time_tracker.py report
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()
Output:
✅ Next invoice number: INV-2026-001
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])
Usage:
python client_log.py add "Acme Corp" call "Discussed Q2 deliverables, 3 revisions allowed"
python client_log.py show "Acme Corp"
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()
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()
Usage:
python deadlines.py add "Homepage Redesign" "2026-03-30" "Acme Corp"
python deadlines.py
Output:
📅 Upcoming Deadlines
--------------------------------------------------
🟡 Homepage Redesign [Acme Corp]: 7 days left
🟢 Mobile App v2 [TechStart]: 14 days left
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)