How to operate the Lobu funnel CRM — create and enrich leads, log interactions, advance funnel stages, open and update pilots, and produce the weekly digest. Use whenever the task touches the pipeline.
Install
npx skillscat add lobu-ai/lobu/crm-ops Install via the SkillsCat registry.
CRM operations
The CRM lives in Lobu memory. Two entity types — lead and pilot — hold current state; events of type lead:* / pilot:* are the append-only history. The converted-to relationship links a lead to the pilot it became.
Funnel stages (the stage field on lead)
signal → trial → conversation → pilot → customer, plus cold (went quiet / not a fit). "Reach" (an impression, a passing tweet view) is not a stage — no lead record until there's a signal.
| Stage | Enter it when… |
|---|---|
signal |
starred the repo, followed on X, @-mentioned Lobu, commented on an issue |
trial |
cloned / ran lobu run / completed the quickstart / asked a real deployment question |
conversation |
DM'd, requested a demo, booked a call, said "we want to deploy this" |
pilot |
signed up for a paid pilot — open a pilot entity, link with converted-to |
customer |
converted from pilot to a paid contract |
cold |
three touches with no response, or explicitly not a fit |
Creating / enriching a lead
- Search first —
search_memory({query: "<github handle | x handle | email | company>"}). If aleadexists, enrich it; don't duplicate. - If new: create the
leadentity with metadata{name, company, source, stage, github_handle, x_handle, email, notes}. Setstageto the lowest stage the evidence supports. save_memory({content: "<who, company, source>", semantic_type: "lead:created", entity_ids: [<lead>, <source connector event>]}).
Logging an interaction
After any touchpoint (a meeting Burak had, a DM exchange, an issue reply you drafted):save_memory({content: "{type, summary, next_action, date}", semantic_type: "lead:interaction", entity_ids: [<lead>]}). Update the lead's notes / stage if the touch moved it (see "advancing a stage").
Advancing a stage
save_memory({content: "{from, to, reason}", semantic_type: "lead:stage_changed", entity_ids: [<lead>]}).- Update the
leadentity'sstagefield.
Never changestagewithout the matching event.
Opening / updating a pilot
- Open: create a
pilotentity{company, seats, mrr, status: "active", start_date, success_metric, lead_id};converted-torelationship from the lead;save_memory({..., semantic_type: "pilot:created", entity_ids: [<pilot>, <lead>]}); move the lead topilot. - Update:
save_memory({content: "{from, to, note}", semantic_type: "pilot:status_changed", entity_ids: [<pilot>]}); update the entity'sstatus(active→won|lost|paused); ifwon, move the lead tocustomer.
Reads the operator asks for
- "who starred us this week and isn't tracked?" — pull recent
stargazerevents (github connector), diff againstleadentities with agithub_handle, return the gap. - "show the pipeline" —
leadentities grouped bystage, each with last-touch date and next action, ranked within stage by closeness-to-pilot. - "state of the pilot?" — the
pilotentity + itspilot:*events, newest first.
Weekly digest (used by the funnel-digest Automation)
A Slack message, in this shape — keep it short:
- One line at the top: the single recommended action this week.
- Funnel snapshot: counts per stage, and what moved (new leads, stage changes, new/updated pilots).
- Top-of-funnel: stars / X mentions / HN+PH activity since last digest.
- Stale leads: anyone in
conversationwith no touch in 7+ days — flag for follow-up. - Gaps: e.g. "12 new stars, 0 became leads — are we capturing the right signal?"
Always end with the next action, never just the status.