Not everything needs a dashboard. Sometimes you just need a quick command-line script that answers a specific question or fixes a specific problem. Here are ten Python CLI scripts that every RevOps team should have in their toolkit, each one solving a real problem in under 50 lines of code.
1. Duplicate Account Detector¶
Find accounts that might be duplicates based on fuzzy name matching:
# dupes.py - Find potential duplicate accounts
from simple_salesforce import Salesforce
from fuzzywuzzy import fuzz
import os, sys
sf = Salesforce(username=os.environ["SF_USERNAME"],
password=os.environ["SF_PASSWORD"], security_token=os.environ["SF_TOKEN"])
threshold = int(sys.argv[1]) if len(sys.argv) > 1 else 85
accounts = sf.query_all("SELECT Id, Name FROM Account ORDER BY Name")["records"]
for i, a in enumerate(accounts):
for b in accounts[i+1:i+10]: # Compare nearby sorted names
score = fuzz.token_sort_ratio(a["Name"], b["Name"])
if score >= threshold:
print(f"[{score}%] '{a['Name']}' <-> '{b['Name']}'")
python dupes.py 90 # Set similarity threshold to 90%
2. Field Utilization Audit¶
Find out which custom fields are actually being used:
# field_audit.py - Check field fill rates on any object
import sys
obj_name = sys.argv[1] if len(sys.argv) > 1 else "Lead"
desc = getattr(sf, obj_name).describe()
for field in desc["fields"]:
if field["custom"]:
query = f"SELECT COUNT(Id) total FROM {obj_name} WHERE {field['name']} != null"
count = sf.query(query)["records"][0]["total"]
pct = (count / total_records * 100) if total_records > 0 else 0
if pct < 10:
print(f" LOW USE: {field['name']} ({pct:.1f}% populated)")
python field_audit.py Opportunity
3. Owner Reassignment Script¶
Bulk reassign records from one owner to another:
# reassign.py - Reassign records between owners
old_owner, new_owner = sys.argv[1], sys.argv[2]
query = f"SELECT Id FROM Account WHERE OwnerId = '{old_owner}'"
records = sf.query_all(query)["records"]
updates = [{"Id": r["Id"], "OwnerId": new_owner} for r in records]
sf.bulk.Account.update(updates, batch_size=200)
print(f"Reassigned {len(updates)} accounts")
4. Stale Pipeline Report¶
List opportunities that have not been modified in N days:
# stale_pipeline.py - Find stale opportunities
days = int(sys.argv[1]) if len(sys.argv) > 1 else 60
query = f"""SELECT Name, StageName, Amount, Owner.Name, LastModifiedDate
FROM Opportunity WHERE IsClosed = false
AND LastModifiedDate < LAST_N_DAYS:{days} ORDER BY Amount DESC"""
for r in sf.query_all(query)["records"]:
print(f"${r['Amount']:>12,.0f} {r['StageName']:<20} {r['Name']}")
5. Data Export to CSV¶
Quick export any SOQL query to CSV:
# export.py - Export any SOQL query to CSV
import csv, sys
query = sys.argv[1]
results = sf.query_all(query)["records"]
if results:
keys = [k for k in results[0].keys() if k != "attributes"]
writer = csv.DictWriter(sys.stdout, fieldnames=keys, extrasaction="ignore")
writer.writeheader()
for r in results:
writer.writerow(r)
python export.py "SELECT Name, Email FROM Contact LIMIT 1000" > contacts.csv
6. Permission Set Checker¶
List all users assigned to a specific permission set:
# perms.py - Check permission set assignments
perm_name = sys.argv[1]
query = f"""SELECT Assignee.Name, Assignee.Profile.Name
FROM PermissionSetAssignment
WHERE PermissionSet.Name = '{perm_name}'"""
for r in sf.query_all(query)["records"]:
print(f"{r['Assignee']['Name']:<30} {r['Assignee']['Profile']['Name']}")
7. Missing Field Finder¶
Identify records that are missing critical fields:
# missing_fields.py - Find records missing required data
required = ["Email", "Phone", "Title", "Company"]
for field in required:
query = f"SELECT COUNT(Id) total FROM Lead WHERE {field} = null AND IsConverted = false"
count = sf.query(query)["records"][0]["total"]
print(f"{field:<20} {count:>6} leads missing")
8. Opportunity Stage Duration¶
Calculate average time spent in each stage:
# stage_duration.py - Avg days in each opportunity stage
query = """SELECT StageName, AVG(days_in_stage__c) avg_days, COUNT(Id) total
FROM Opportunity WHERE IsClosed = true AND IsWon = true
GROUP BY StageName ORDER BY StageName"""
for r in sf.query(query)["records"]:
print(f"{r['StageName']:<25} {r['avg_days']:>6.1f} days ({r['total']} deals)")
9. Inactive User Report¶
Find active licenses assigned to users who have not logged in recently:
# inactive_users.py - Users who haven't logged in for 90+ days
query = """SELECT Name, Profile.Name, LastLoginDate
FROM User WHERE IsActive = true
AND LastLoginDate < LAST_N_DAYS:90 ORDER BY LastLoginDate"""
for r in sf.query_all(query)["records"]:
print(f"{r['Name']:<30} Last login: {r['LastLoginDate'][:10]}")
10. Quick Record Count Dashboard¶
Get a snapshot of record counts across your key objects:
# counts.py - Record counts for key objects
objects = ["Account", "Contact", "Lead", "Opportunity", "Case"]
for obj in objects:
count = sf.query(f"SELECT COUNT(Id) total FROM {obj}")["records"][0]["total"]
print(f"{obj:<15} {count:>10,}")
python counts.py
# Account 12,458
# Contact 45,231
# Lead 23,890
# Opportunity 8,432
# Case 15,678
Key Takeaways¶
- A library of small, single-purpose CLI scripts is more practical than one monolithic tool that tries to do everything
- Each script in this toolkit solves a specific problem in under 50 lines, making them easy to understand, modify, and maintain
- CLI scripts integrate naturally into cron jobs, CI/CD pipelines, and other automation workflows
- Start with the two or three scripts that address your biggest pain points and grow the toolkit over time