CRM-Lite — Lightweight SQLite CRM for Small Business skill
Use when tracking customer interactions, managing leads, or building a lightweight CRM for small businesses without dedicated CRM software.
by hewi333·MIT license·★ 122 Stars on the repo·GitHub ↗
npx degit hewi333/Mom-n-Pop-Skills/skills/crm-lite#main ~/.claude/skills/crm-liteChecked ·commit main
Inside this skill
SKILL.md · the author's own words# CRM-Lite — Lightweight SQLite CRM for Small Business ## Overview A minimal, file-based CRM built on SQLite for non-technical small business owners. No server, no external dependencies, no auth complexity.… ## When to Use - **Small business** (1-10 employees) with no existing CRM - **Agent-mediated access** — owners interact via chat/Telegram, not direct DB access - **Lead tracking** from website forms, referrals, email inquiries - **Pipeline visibility** — estimate sent → accepted/rejected → job scheduled → paid - **Communication log** — every email, call, text logged automatically ## Don't Use For - Multi-user concurrent access with role-based permissions - Complex sales methodologies (MEDDIC, Challenger, etc.) - Real-time collaboration features
Word-for-word excerpt, not a result. Read the full SKILL.md ↓
Files of CRM-Lite — Lightweight SQLite CRM for Small Business
Show the full text150 lines
CRM-Lite — Lightweight SQLite CRM for Small Business
Overview
A minimal, file-based CRM built on SQLite for non-technical small business owners. No server, no external dependencies, no auth complexity. Designed for agent-mediated use: the owner interacts via text message with the agent, which reads/writes this database.
When to Use
- Small business (1-10 employees) with no existing CRM
- Agent-mediated access — owners interact via chat/Telegram, not direct DB access
- Lead tracking from website forms, referrals, email inquiries
- Pipeline visibility — estimate sent → accepted/rejected → job scheduled → paid
- Communication log — every email, call, text logged automatically
Don't Use For
- Multi-user concurrent access with role-based permissions
- Complex sales methodologies (MEDDIC, Challenger, etc.)
- Real-time collaboration features
- Integration with enterprise SSO/SCIM
Core Features
Data Model (SQLite: crm.db)
customers — Core customer records
id(PK),name,email,phone,company,address,city,state,ziplead_source,lead_status(new/qualified/estimate_sent/won/lost)total_value,notes,created_at,updated_at
leads — Inbound leads before qualification
id,source(website/referral/email/phone),contact_namecontact_email,contact_phone,company,property_addresssqft,ceiling_height,service_type,urgencystatus(new/qualified/estimate_ready/scheduled/lost)assigned_to,created_at,updated_at
activities — Every touchpoint
id,customer_id(FK),lead_id(FK),activity_type(call/email/text/meeting/estimate_sent/estimate_accepted/estimate_rejected/job_scheduled/job_completed/invoice_sent/payment_received)description,outcome,next_action,next_action_datecreated_at,updated_at
estimates — Estimate lifecycle
id,customer_id,lead_id,estimate_number,amountstatus(draft/sent/accepted/rejected/expired)sent_date,accepted_date,rejected_date,expires_dateline_items(JSON),notes,created_at,updated_at
communications — Message log
id,customer_id,lead_id,direction(inbound/outbound)channel(email/sms/telegram/phone),subject,bodysent_at,created_at
tasks — Action items for owners
id,customer_id,lead_id,title,descriptiondue_date,priority(low/medium/high/urgent),status(pending/in_progress/done)assigned_to,created_at,updated_at
Quick Start
import sqlite3
from pathlib import Path
DB_PATH = Path("~/.hermes/crm/crm.db").expanduser()
DB_PATH.parent.mkdir(parents=True, exist_ok=True)
def init_db():
conn = sqlite3.connect(DB_PATH)
conn.execute("""
CREATE TABLE IF NOT EXISTS customers (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL, email TEXT, phone TEXT,
company TEXT, address TEXT, city TEXT, state TEXT, zip TEXT,
lead_source TEXT, lead_status TEXT DEFAULT 'new',
total_value REAL DEFAULT 0, notes TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
)
""")
# ... other tables
conn.commit()
return conn
Agent Integration Patterns
Create Lead from Website Form
User: "New lead from website: John Smith, [email protected], 555-555-0123, 123 Main St [CITY] [STATE] [ZIP], 2500 sqft, service request"
Agent: Creates lead record, sets status=qualified, creates task for the owner to review
Log Estimate Sent
User: "Sent estimate #EST-0001-0042 to John Smith for $2,850"
Agent: Updates estimate status=sent, creates activity, creates task for follow-up in 3 days
Weekly Pipeline Report (Cron)
Agent: Queries all leads/customers, summarizes by stage, sends to the owner via Telegram
Common Pitfalls
- Forgetting to create indexes — Add indexes on
customers.email,leads.status,activities.customer_idfor query speed - Not backing up — SQLite file is the entire DB; copy to S3/Drive daily via cron
- Schema drift — Use migrations (numbered SQL files) rather than ad-hoc ALTER TABLE
- Concurrent writes — SQLite handles concurrent reads, but writes serialize; keep transactions short
Verification Checklist
-
crm.dbcreated with all 6 tables - Indexes on foreign keys and query columns
- Agent can: create lead, log activity, update estimate status, create task
- Weekly report cron outputs: new leads, estimates sent, conversion rate, pipeline value
- Backup script copies DB to offsite location daily
One-Shot Recipes
"New lead from referral"
conn = init_db()
lead_id = conn.execute("""
INSERT INTO leads (source, contact_name, contact_email, contact_phone, company, property_address, sqft, service_type, status)
VALUES ('referral', 'Jane Doe', '[email protected]', '555-555-0199', 'Example Realty', '456 Palm Ave [CITY] [STATE] [ZIP]', 3200, 'service_request', 'qualified')
""").lastrowid
conn.commit()
"Get pipeline summary for weekly report"
summary = conn.execute("""
SELECT
COUNT(CASE WHEN lead_status='new' THEN 1 END) as new_leads,
COUNT(CASE WHEN lead_status='estimate_sent' THEN 1 END) as estimates_out,
COUNT(CASE WHEN lead_status='won' THEN 1 END) as won,
SUM(CASE WHEN lead_status='won' THEN total_value ELSE 0 END) as revenue
FROM customers
""").fetchone()
| 1 | |
| 2 | name crm-lite |
| 3 | description "Use when tracking customer interactions, managing leads, or building a lightweight CRM for small businesses without dedicated CRM software. Stores contacts, leads, activities, estimates, and communications in local SQLite." |
| 4 | version "1.0.0" |
| 5 | author Hermes Agent |
| 6 | license MIT |
| 7 | metadata |
| 8 | hermes |
| 9 | tags [crm, sqlite, small-business, customer-management] |
| 10 | related_skills [estimator-engine, quickbooks-online, mailchimp-integration, stripe-payments, outlook-graph, small-business-website-spec] |
| 11 | |
| 12 | |
| 13 | # CRM-Lite — Lightweight SQLite CRM for Small Business |
| 14 | |
| 15 | ## Overview |
| 16 | A minimal, file-based CRM built on SQLite for non-technical small business owners. No server, no external dependencies, no auth complexity. Designed for agent-mediated use: the owner interacts via text message with the agent, which reads/writes this database. |
| 17 | |
| 18 | ## When to Use |
| 19 | **Small business** (1-10 employees) with no existing CRM |
| 20 | **Agent-mediated access** — owners interact via chat/Telegram, not direct DB access |
| 21 | **Lead tracking** from website forms, referrals, email inquiries |
| 22 | **Pipeline visibility** — estimate sent → accepted/rejected → job scheduled → paid |
| 23 | **Communication log** — every email, call, text logged automatically |
| 24 | |
| 25 | ## Don't Use For |
| 26 | Multi-user concurrent access with role-based permissions |
| 27 | Complex sales methodologies (MEDDIC, Challenger, etc.) |
| 28 | Real-time collaboration features |
| 29 | Integration with enterprise SSO/SCIM |
| 30 | |
| 31 | ## Core Features |
| 32 | |
| 33 | ### Data Model (SQLite: `crm.db`) |
| 34 | **customers** — Core customer records |
| 35 | `id` (PK), `name`, `email`, `phone`, `company`, `address`, `city`, `state`, `zip` |
| 36 | `lead_source`, `lead_status` (new/qualified/estimate_sent/won/lost) |
| 37 | `total_value`, `notes`, `created_at`, `updated_at` |
| 38 | |
| 39 | **leads** — Inbound leads before qualification |
| 40 | `id`, `source` (website/referral/email/phone), `contact_name` |
| 41 | `contact_email`, `contact_phone`, `company`, `property_address` |
| 42 | `sqft`, `ceiling_height`, `service_type`, `urgency` |
| 43 | `status` (new/qualified/estimate_ready/scheduled/lost) |
| 44 | `assigned_to`, `created_at`, `updated_at` |
| 45 | |
| 46 | **activities** — Every touchpoint |
| 47 | `id`, `customer_id` (FK), `lead_id` (FK), `activity_type` (call/email/text/meeting/estimate_sent/estimate_accepted/estimate_rejected/job_scheduled/job_completed/invoice_sent/payment_received) |
| 48 | `description`, `outcome`, `next_action`, `next_action_date` |
| 49 | `created_at`, `updated_at` |
| 50 | |
| 51 | **estimates** — Estimate lifecycle |
| 52 | `id`, `customer_id`, `lead_id`, `estimate_number`, `amount` |
| 53 | `status` (draft/sent/accepted/rejected/expired) |
| 54 | `sent_date`, `accepted_date`, `rejected_date`, `expires_date` |
| 55 | `line_items` (JSON), `notes`, `created_at`, `updated_at` |
| 56 | |
| 57 | **communications** — Message log |
| 58 | `id`, `customer_id`, `lead_id`, `direction` (inbound/outbound) |
| 59 | `channel` (email/sms/telegram/phone), `subject`, `body` |
| 60 | `sent_at`, `created_at` |
| 61 | |
| 62 | **tasks** — Action items for owners |
| 63 | `id`, `customer_id`, `lead_id`, `title`, `description` |
| 64 | `due_date`, `priority` (low/medium/high/urgent), `status` (pending/in_progress/done) |
| 65 | `assigned_to`, `created_at`, `updated_at` |
| 66 | |
| 67 | ## Quick Start |
| 68 | |
| 69 | |
| 70 | import sqlite3 |
| 71 | from pathlib import Path |
| 72 | |
| 73 | DB_PATH = Path("~/.hermes/crm/crm.db").expanduser() |
| 74 | DB_PATH.parent.mkdir(parents=True, exist_ok=True) |
| 75 | |
| 76 | def init_db(): |
| 77 | conn = sqlite3.connect(DB_PATH) |
| 78 | conn.execute(""" |
| 79 | CREATE TABLE IF NOT EXISTS customers ( |
| 80 | id INTEGER PRIMARY KEY AUTOINCREMENT, |
| 81 | name TEXT NOT NULL, email TEXT, phone TEXT, |
| 82 | company TEXT, address TEXT, city TEXT, state TEXT, zip TEXT, |
| 83 | lead_source TEXT, lead_status TEXT DEFAULT 'new', |
| 84 | total_value REAL DEFAULT 0, notes TEXT, |
| 85 | created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, |
| 86 | updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP |
| 87 | ) |
| 88 | """) |
| 89 | # ... other tables |
| 90 | conn.commit() |
| 91 | return conn |
| 92 | |
| 93 | |
| 94 | ## Agent Integration Patterns |
| 95 | |
| 96 | ### Create Lead from Website Form |
| 97 | |
| 98 | User: "New lead from website: John Smith, [email protected], 555-555-0123, 123 Main St [CITY] [STATE] [ZIP], 2500 sqft, service request" |
| 99 | Agent: Creates lead record, sets status=qualified, creates task for the owner to review |
| 100 | |
| 101 | |
| 102 | ### Log Estimate Sent |
| 103 | |
| 104 | User: "Sent estimate #EST-0001-0042 to John Smith for $2,850" |
| 105 | Agent: Updates estimate status=sent, creates activity, creates task for follow-up in 3 days |
| 106 | |
| 107 | |
| 108 | ### Weekly Pipeline Report (Cron) |
| 109 | |
| 110 | Agent: Queries all leads/customers, summarizes by stage, sends to the owner via Telegram |
| 111 | |
| 112 | |
| 113 | ## Common Pitfalls |
| 114 | |
| 115 | **Forgetting to create indexes** — Add indexes on `customers.email`, `leads.status`, `activities.customer_id` for query speed |
| 116 | **Not backing up** — SQLite file is the entire DB; copy to S3/Drive daily via cron |
| 117 | **Schema drift** — Use migrations (numbered SQL files) rather than ad-hoc ALTER TABLE |
| 118 | **Concurrent writes** — SQLite handles concurrent reads, but writes serialize; keep transactions short |
| 119 | |
| 120 | ## Verification Checklist |
| 121 | |
| 122 | [ ] `crm.db` created with all 6 tables |
| 123 | [ ] Indexes on foreign keys and query columns |
| 124 | [ ] Agent can: create lead, log activity, update estimate status, create task |
| 125 | [ ] Weekly report cron outputs: new leads, estimates sent, conversion rate, pipeline value |
| 126 | [ ] Backup script copies DB to offsite location daily |
| 127 | |
| 128 | ## One-Shot Recipes |
| 129 | |
| 130 | ### "New lead from referral" |
| 131 | |
| 132 | conn = init_db() |
| 133 | lead_id = conn.execute(""" |
| 134 | INSERT INTO leads (source, contact_name, contact_email, contact_phone, company, property_address, sqft, service_type, status) |
| 135 | VALUES ('referral', 'Jane Doe', '[email protected]', '555-555-0199', 'Example Realty', '456 Palm Ave [CITY] [STATE] [ZIP]', 3200, 'service_request', 'qualified') |
| 136 | """).lastrowid |
| 137 | conn.commit() |
| 138 | |
| 139 | |
| 140 | ### "Get pipeline summary for weekly report" |
| 141 | |
| 142 | summary = conn.execute(""" |
| 143 | SELECT |
| 144 | COUNT(CASE WHEN lead_status='new' THEN 1 END) as new_leads, |
| 145 | COUNT(CASE WHEN lead_status='estimate_sent' THEN 1 END) as estimates_out, |
| 146 | COUNT(CASE WHEN lead_status='won' THEN 1 END) as won, |
| 147 | SUM(CASE WHEN lead_status='won' THEN total_value ELSE 0 END) as revenue |
| 148 | FROM customers |
| 149 | """).fetchone() |
| 150 |
Discussion
Alternatives
Browse more free Claude skills or everything in Sales.