一键导入
database-crm-system
// Manage DuckDB CRM data, aggressive relation-linked fields, and synced markdown documents in the workspace. Use when creating or updating objects, fields, entries, foreign-table links, row notes, or entry-linked edit logs.
// Manage DuckDB CRM data, aggressive relation-linked fields, and synced markdown documents in the workspace. Use when creating or updating objects, fields, entries, foreign-table links, row notes, or entry-linked edit logs.
Connected app tool recipes for Composio integrations (Gmail, Slack, GitHub, Notion, Google Calendar, Linear)
Find and connect with engineers working on ELK/observability stacks at ICP companies. Use when: (1) Researching individual contributors at a company that passed ICP company research, (2) Finding engineers with ELK/platform/SRE skills, (3) Verifying someone's work involves ELK/logstash/observability, (4) Connecting with practitioners who manage the stack day-to-day, (5) Discovering new ICP companies through engineer profiles. Workflow: Company from CRM → DuckDuckGo → PinchTab → LinkedIn MCP (verify ELK in skills/experience + connect) → Add to engineers CRM. Flipped discovery: If engineer has strong ELK signals but company isn't in CRM → add company as 'Discovered'. This skill DOES connect on LinkedIn.
Find and connect with team leads/VPs running observability/ELK stacks at ICP companies. Use when: (1) Researching decision-makers at a company that passed ICP company research, (2) Finding VP/Director/Team Lead contacts (VP Platform, Director SRE, Infrastructure Lead), (3) Verifying someone's role includes observability/platform, (4) Connecting with buyers who have budget authority, (5) Discovering new ICP companies through team lead profiles. Workflow: Company from CRM → DuckDuckGo → PinchTab → LinkedIn MCP (verify + connect) → Add to team_leads CRM. Flipped discovery: If team lead runs platform/observability but company isn't in CRM → add company as 'Discovered'. This skill DOES connect on LinkedIn.
Debugging CRM objects not showing entries despite data existing in database
Research companies against ICP criteria for ELK/observability tools. Use when: (1) Finding companies that match ICP (MSSPs, SOC-as-a-service, SIEM providers, cybersecurity where observability IS their product), (2) Evaluating if a company fits the ideal customer profile, (3) Researching company size, business model, and ELK criticality, (4) Building prospect lists for outreach. ICP: Small-medium companies (≤200 employees) where observability/ELK is mission-critical to revenue. Use DuckDuckGo first, then PinchTab for deeper research, then LinkedIn MCP ONLY for company/people lookup (never for outreach).
Browser automation for general web browsing, reading blogs, Googling, and extracting website information. Use PinchTab when you need to interact with websites that don't have dedicated MCP servers. For Reddit tasks, use reddit-mcp. For LinkedIn tasks, use linkedin-mcp - NEVER use PinchTab for LinkedIn. Use PinchTab for: (1) Searching Google and browsing search results, (2) Reading blogs and articles, (3) General web surfing when no dedicated tool exists, (4) Taking screenshots of websites, (5) Extracting text content from pages, (6) Testing websites or debugging web issues.
| name | database-crm-system |
| description | Manage DuckDB CRM data, aggressive relation-linked fields, and synced markdown documents in the workspace. Use when creating or updating objects, fields, entries, foreign-table links, row notes, or entry-linked edit logs. |
| metadata | {"openclaw":{"inject":true,"always":true,"emoji":"📊"}} |
You manage a CRM workspace stored at /Users/collinpfeifer/.openclaw-dench/workspace.
All structured data lives in DuckDB. The primary database is /Users/collinpfeifer/.openclaw-dench/workspace/workspace.duckdb, but subdirectories may contain their own workspace.duckdb that is authoritative for objects in that subtree (hierarchical DB discovery). Shallower databases take priority when objects share the same name. Documents are markdown files in /Users/collinpfeifer/.openclaw-dench/workspace/**. Organization context will be in /Users/collinpfeifer/.openclaw-dench/workspace/workspace_context.yaml if an organisation exists (READ-ONLY).
All actions should look into / edit and work on /Users/collinpfeifer/.openclaw-dench/workspace/** by default unless told otherwise. Exceptions to this are the SOUL.md, skills/, memory/, USER.md, IDENTITY.md, TOOLS.md, AGENTS.md and MEMORY.md and other such files.
All your workspace chats and past conversations are stored in /Users/collinpfeifer/.openclaw-dench/workspace/.openclaw/web-chat/.
/Users/collinpfeifer/.openclaw-dench/workspace/
workspace_context.yaml # READ-ONLY org context (members, integrations, protected objects)
workspace.duckdb # DuckDB database — sole source of truth for structured data
people/ # Object directory
.object.yaml # Object metadata projection
onboarding-guide.md # Document nested under object
companies/
.object.yaml
projects/
projects.md # Document content
tasks/ # Object nested under document
.object.yaml
exports/ # On-demand CSV/Parquet exports
WORKSPACE.md # Auto-generated schema summary
On every conversation:
/Users/collinpfeifer/.openclaw-dench/workspace/workspace_context.yaml for org context, members, integrations, protected objects. NEVER modify this file.curl https://install.duckdb.org | sh/Users/collinpfeifer/.openclaw-dench/workspace/workspace.duckdb does not exist, initialize it with the schema in the duckdb-operations child skill.This file is generated by the CRM system and synced via S3. It contains:
organization: id, name, slug, business infomembers: Team members with IDs, names, emails, roles. Use these IDs for "user" type fields (e.g., "Assigned To").protected_objects: Objects that MUST NOT be deleted or renamed (e.g., people, companies).integrations: Connected apps with sync direction, frequency, and field mappings.enrichment: Whether enrichment is enabled and which provider.defaults: Default view, date format, naming conventions.credits: Current credit balance for enrichment/AI operations.name, the filesystem directory name, and the .object.yaml name field MUST all be identical. If any one of these three diverges, the UI will fail to render the object. For example, if DuckDB has name = 'contract', the directory MUST be contract/ (in workspace) and the yaml MUST have name: "contract". Never use plural for one and singular for another.When renaming or relocating an object, you MUST update ALL THREE in a single operation:
objects.name (if FK constraints block this, recreate the object with the new name and migrate entries)mv the old directory to the new name.object.yaml: Update the name field to matchDROP VIEW IF EXISTS v_{old_name}; CREATE OR REPLACE VIEW v_{new_name} ...Never rename partially. If you can't complete all steps, don't start the rename — explain the constraint to the user first.
UNIQUE constraint on INSERT: item already exists — use ON CONFLICT DO NOTHING or DO UPDATE. Treat as success.immutable column AND protected_objects in workspace_context.yaml. NEVER delete protected objects."Full Name" not Full Name), wrong transaction syntax (BEGIN TRANSACTION not BEGIN), unescaped single quotes, and PIVOT views without the IN (...) field list..actions/ directory and/or script files were not created. See the actions child skill post-creation checklist.Every time you create or modify objects or fields, check whether relation fields should connect them. Do NOT wait for the user to ask — proactively link objects that are obviously related.
Relation fields (type: "relation") let an entry in one object reference an entry in another. They render as a searchable dropdown in the UI and are the backbone of any useful CRM.
Treat relation fields as the CRM's default foreign-link primitive. If a field can reasonably point at another object, prefer a relation field over text, richtext, or some copied label string.
When you create an object, or add/modify a field on an existing object, scan all existing objects (run SELECT name FROM objects) and add relation fields for every obvious link:
| If you're creating... | And this object exists... | Auto-create this relation field |
|---|---|---|
| people / contact | company | "Company" on people → company (many_to_one) |
| lead / prospect | company | "Company" on lead → company (many_to_one) |
| deal / opportunity | people | "Primary Contact" on deal → people (many_to_one) |
| deal / opportunity | company | "Company" on deal → company (many_to_one) |
| task | people | "Assigned Contact" on task → people (many_to_one) |
| task | project / deal | "Related To" on task → parent (many_to_one) |
| case | people or company | "Client" on case → people/company (many_to_one) |
| invoice / payment | company | "Company" on invoice → company (many_to_one) |
| invoice / payment | deal | "Deal" on invoice → deal (many_to_one) |
| property / listing | people | "Agent" on property → people (many_to_one) |
| any child concept | its parent concept | relation to parent (many_to_one) |
Use this SQL pattern (safe — does nothing if the target object doesn't exist):
INSERT INTO fields (object_id, name, type, related_object_id, relationship_type, sort_order)
SELECT
(SELECT id FROM objects WHERE name = 'people'),
'Company',
'relation',
(SELECT id FROM objects WHERE name = 'company'),
'many_to_one',
3
WHERE EXISTS (SELECT 1 FROM objects WHERE name = 'company')
ON CONFLICT (object_id, name) DO NOTHING;
General rule: If you're creating object B or field F on object B and object A already exists, ask: "Would an entry in B logically belong to, reference, select, or connect to an entry in A?" If yes, add a relation field. Use many_to_one by default. Use many_to_many only when the field is clearly plural or multi-select (e.g. project → team members).
relation field.relation field instead of a text field.Company Name, Client Name, Project Name, Deal Name, Owner Name, or similar if the corresponding object already exists, unless the user explicitly wants a denormalized snapshot.user, not text.text; ask only when the ambiguity would materially change the schema.Relation fields must be created via SQL — the API does not support the relation type.
{object}/.object.yaml in workspace AND the v_{object} view. If you skip this, the object will be invisible in the sidebar. This is NOT optional.SELECT before INSERT, or ON CONFLICT)v_{object}) for all reads — never write raw PIVOT queries for searchSELECT * FROM fields WHERE object_id = ?date field, use created_at/updated_at (from entries) instead of saying there are no date fields..report.json format (see reports child skill), NOT markdown. Only use markdown .md for SOPs, guides, notes, and prose documents.report-json fenced code block so the UI renders interactive charts inline.Notes is a DuckDB richtext field stored in entry_fields. Entry documents are markdown files linked through the documents table. References to "notes" on a row or entry default to the connected entry document unless the user explicitly says Notes field/column or needs table/filter/SQL semantics.yt-mikemurphy-001.md, jane-smith-001.md, acme-corp-001.md) and MUST be registered in DuckDB documents with file_path, parent_object_id, and entry_id. Reuse an existing linked document when present; otherwise create one and keep it synced on every mutation. Do NOT default to raw {entry_id}.md filenames for new docs. See documents child skill.workspace_context.yaml BEFORE insertingenum_values JSON array'["tag1","tag2"]'"action" with default_value containing {"actions":[...]} JSON. Action fields are excluded from PIVOT views. When using file-based scripts (scriptPath), you MUST also: (1) mkdir -p the .actions/ directory, (2) write every script file referenced in the config, (3) update .object.yaml with action_config. If you skip creating the script files, the button will render but clicking it shows "Script not found". See actions child skill for the mandatory post-creation checklist and a complete end-to-end example.default_view = 'kanban', set view_settings.kanbanField: "Status", auto-create Status and Assigned To fieldsdefault_view = 'calendar', set view_settings.calendarDateField to the date fielddefault_view = 'timeline', set view_settings.timelineStartField and optionally timelineEndFielddefault_view values: table, kanban, calendar, timeline, gallery, list.object.yaml and set active_view so the UI updates immediately. Do this even if they did not explicitly ask to "create a view", unless they clearly want a one-off answer only.columns by default. If columns is not present, the table uses the default/all columns. views[].columns controls visibility only, not display order. Only write columns when the user explicitly asks for a specific visible subset.views[].columns. Update the object's field sort_order in DuckDB, then regenerate .object.yaml so its top-level fields list matches the new schema order.view_settings.column_widths (object-level) or views[].column_widths (per-view) as a map of field name to pixel width (e.g. column_widths: { "Full Name": 250, "Status": 150 }). The UI also auto-persists widths when columns are drag-resized.workspace_context.yaml protected_objects"Full Name", "Email Address", etc. Without quotes, DuckDB treats them as separate identifiers and the query fails.IN (...) clause to list field names explicitly. Exclude action fields with AND f.type != 'action'. See duckdb-operations child skill.entry_count in .object.yaml.objects.name, the filesystem directory name, and .object.yaml name MUST be identical. See Naming Conventions above.tmp/ directory (create it in the workspace if it doesn't exist, only if needed).This skill covers workspace fundamentals. For specialized operations, see these child skills (all inside the crm/ skill folder):
| Skill | Path | Covers |
|---|---|---|
| DuckDB Operations | crm/duckdb-operations/SKILL.md | DuckDB schema initialization, field types reference, auto-generated PIVOT views, SQL CRUD operations (create/read/update/delete objects, fields, entries), bulk import/export |
| Object Builder | crm/object-builder/SKILL.md | Full 3-step workflow (SQL → filesystem → verify), CRM patterns (contact, lead, company, deal, case, property, task), kanban boards, post-mutation checklist, renaming objects |
| Views & Filters | crm/views-filters/SKILL.md | .object.yaml format and template, view type settings (kanban, calendar, timeline, gallery, list), saved views, filter operators by field type, date format rules |
| Documents | crm/documents/SKILL.md | Document management (markdown files), cross-nesting (documents under objects, objects under documents), default connected entry pages, and entry mutation/edit logs |
| Reports | crm/reports/SKILL.md | Report generation (.report.json format), chart types (bar, line, area, pie, donut, radar, scatter, funnel), panel sizes, filter types, inline chat reports, post-report checklist |
| Actions | crm/actions/SKILL.md | Action field type (type: "action"), executable buttons on entries, server-side script execution in any language (JS, Python, bash, etc.), inline JS SDK, NDJSON stdout protocol, environment variable context, bulk parallel execution, action_runs table, UI rendering in table/kanban/entry panel |
All child skills are seeded into the workspace alongside this parent skill and can be read at /Users/collinpfeifer/.openclaw-dench/workspace/skills/crm/<child>/SKILL.md.