.cursor/skills/extract-erd/SKILL.md
Derive a true ERD (Mermaid diagram) from a FileMaker solution by analyzing table occurrences, relationships, and fields. Collapses utility TOs to base tables and presents all relationships for developer classification. Use when the user asks to "extract ERD", "show ERD", "map the schema", "understand the database", or wants a high-level overview of a solution's data model.
npx skillsauth add petrowsky/agentic-fm extract-erdInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
This skill analyzes a FileMaker solution's relationship graph and produces a true ERD as a Mermaid diagram — collapsing utility table occurrences down to base tables and letting the developer classify which relationships represent genuine entity connections.
Purpose: Give a developer who is new to a solution a quick, accurate, high-level understanding of its data model.
Output: A Mermaid erDiagram file written to agent/sandbox/.
Metric: Minimize tool calls from invocation to ERD ready for developer review.
Key rules:
The skill uses two possible data sources, in order of preference:
When agent/context/{solution}/ exists with index files:
table_occurrences.index — TO-to-base-table mapping (columns: TOName|TOID|BaseTableName|BaseTableID)relationships.index — all relationships between TOs (columns: LeftTO|LeftTOID|RightTO|RightTOID|JoinType|JoinFields|CascadeCreate|CascadeDelete)fields.index — all fields per base table (columns: TableName|TableID|FieldName|FieldID|DataType|FieldType|AutoEnter|Flags)$metadata endpoint (fallback)When index files are not available but agent/config/automation.json has an odata block for the solution:
{base_url}/{database}/$metadata with Basic authEntityType elements for fields and typesNavigationProperty and NavigationPropertyBinding for relationshipsIf neither source is available, instruct the developer to either run Explode XML or configure OData access.
List subdirectories under agent/context/ using Bash ls.
automation.json for OData config and fall back to the OData path.Index file path — read all three files in parallel:
Once the solution name is known, read all three index files simultaneously in a single parallel batch:
agent/context/{solution}/table_occurrences.indexagent/context/{solution}/relationships.indexagent/context/{solution}/fields.indexThese files have zero dependencies between them. Never read them sequentially.
OData path:
$metadata from the OData endpoint (single request contains everything)EntityType elements — field names, types, and annotationsNavigationProperty elements — TO-level relationshipsProcess all three data sources together in one pass. Do not separate collapse, table classification, and relationship pre-classification into distinct sequential steps — they use the same data and can be computed together.
Collapse: For each relationship, resolve both sides from TO names to base table names. Group multiple TO-level relationships between the same two base tables.
For each base-table pair, collect:
Classify tables into one of three categories (suggestions only — the developer makes the final call):
ENTITY — a first-class business object that exists independently:
PrimaryKey fieldJOIN — exists primarily to connect two entities (associative/junction table):
PrimaryKey fieldForeignKey* fields pointing to other tablesUTILITY — a table that supports the solution but is not part of the core data model:
Heuristics to auto-classify:
| Signal | Points toward | |--------|--------------| | 2+ ForeignKey fields | JOIN | | Cascade delete enabled on a parent relationship | JOIN | | Few non-key, non-timestamp fields | JOIN | | Multiple global fields | UTILITY | | No inbound FK references from other tables | UTILITY | | Rich descriptive fields (Name, Address, Phone, etc.) | ENTITY | | Other tables reference it via FK | ENTITY |
Pre-classify relationships — apply heuristics to suggest a classification for each base-table relationship (suggestions only):
Likely TRUE ERD:
PrimaryKey on one side and a ForeignKey* field on the otherEqualForeignKey{TableName}, FK{TableName}, {TableName}ID)Likely UTILITY:
ForeignKeyStaff = CreationTimestamp)Equal (cartesian, inequality joins)UNCERTAIN:
Display a structured report with three sections:
List each base table with its classification, TO count, and total field count:
Base Tables (N total):
1. Clients ENTITY — 2 TOs (Clients Primary, Clients Secondary) — 26 fields
2. Invoices ENTITY — 3 TOs (Invoices, Invoices 2, Invoices 3) — 23 fields
3. Line Items JOIN — 2 TOs (Line Items, Line Items 2) — 13 fields
4. Products ENTITY — 1 TO (Products) — 13 fields
5. Staff ENTITY — 1 TO (Staff) — 16 fields
6. Admin UTILITY — 1 TO (Admin) — 25 fields
For each base-table-level relationship, show:
Relationship N: Clients → Invoices
Classification: TRUE ERD
Reasoning: PrimaryKey = ForeignKeyClient (PK→FK pattern, Equal join)
TO pairs:
• Clients Primary → Invoices | PrimaryKey = ForeignKeyClient | Equal | no cascade
Suggested cardinality: one-to-many (1 Client has many Invoices)
Relationship N: Invoices → Invoices (self-join)
Classification: UTILITY
Reasoning: ForeignKeyStaff = CreationTimestamp — non-PK/FK join fields, likely a filtered portal relationship
TO pairs:
• Invoices → Invoices 2 | ForeignKeyStaff = CreationTimestamp | Equal | no cascade
• Invoices → Invoices 3 | ForeignKeyStaff = ForeignKeyClient | Equal | no cascade
Use a single AskUserQuestion call to present the full report and ask both questions at once:
Prompt: Present the report above, then ask:
Review the table and relationship classifications above. Reply with any changes (e.g., "Line Items is an ENTITY not a JOIN", "Relationship 3 should be TRUE ERD") or confirm with "looks good".
Also, how much field detail in the diagram?
- Full — all fields per table (best for small solutions, can be large for 100+ field tables)
- Keys only — PrimaryKey and ForeignKey fields only (compact, focuses on relationships)
- Keys + business fields — PKs, FKs, and non-system fields (excludes CreationTimestamp, CreatedBy, ModificationTimestamp, ModifiedBy, FoundCount, and similar audit/system fields)
Default is option 3 if you don't have a preference.
For solutions with any table exceeding 50 fields, mention the field counts and recommend option 2 or 3.
This batches two developer interactions into one round-trip. If the developer adjusts any classifications, update accordingly before proceeding.
These two operations are tightly coupled — cardinality feeds directly into diagram generation. Perform them in a single pass.
For each confirmed TRUE ERD relationship, infer cardinality:
| Pattern | Cardinality | Mermaid syntax |
|---------|-------------|----------------|
| PK on left, FK on right | One-to-many | \|\|--o{ |
| FK on left, PK on right | Many-to-one | }o--\|\| |
| PK on both sides | One-to-one | \|\|--\|\| |
| FK on both sides | Many-to-many (rare in FM) | }o--o{ |
When the pattern is ambiguous, default to one-to-many and add a comment.
Build an erDiagram with:
ForeignKeyClient → "has" or "belongs to")Add a Mermaid comment (%%) above each table indicating its classification (ENTITY or JOIN) so the diagram is self-documenting.
| Mode | Include | Exclude |
|------|---------|---------|
| Full | All fields | Nothing |
| Keys only | PrimaryKey, ForeignKey*, FK* fields | Everything else |
| Keys + business | All fields except system/audit fields | CreationTimestamp, CreatedBy, ModificationTimestamp, ModifiedBy, FoundCount, and fields with global flag |
Map FileMaker field types to concise Mermaid-compatible labels:
| FileMaker type | Mermaid label | |----------------|---------------| | Text | text | | Number | number | | Date | date | | Timestamp | timestamp | | Time | time | | Binary (Container) | container |
| Condition | Annotation |
|-----------|------------|
| Field named PrimaryKey or has notEmpty,unique flags | PK |
| Field name starts with ForeignKey or FK | FK |
| FieldType is Calculated | (append type from calc, keep annotation if PK/FK) |
| FieldType is Summary | (label as summary) |
erDiagram
%% ENTITY
Clients {
text PrimaryKey PK
text Name
text ContactFirstName
text ContactLastName
number InvoiceCount
}
%% ENTITY
Invoices {
text PrimaryKey PK
text ForeignKeyClient FK
text ForeignKeyStaff FK
date Date
number Total
}
%% JOIN
LineItems {
text PrimaryKey PK
text ForeignKeyInvoice FK
text ForeignKeyProduct FK
number Qty
number Amount
number LineSubtotal
}
Clients ||--o{ Invoices : "has"
Staff ||--o{ Invoices : "assigned"
Invoices ||--o{ LineItems : "contains"
LineItems }o--|| Products : "references"
Write the Mermaid file to agent/sandbox/{solution-name}-erd.md with a brief header:
# {Solution Name} — Entity Relationship Diagram
Generated: {date}
Source: {index files | OData $metadata}
Relationships: {N true ERD} confirmed, {N utility} excluded
{mermaid diagram}
Report the file path to the developer.
;-separated in the index). Show all predicates — compound joins are more likely to be utility relationships.User: "I'm new to this solution — can you map out the database for me?"
ls agent/context/ → Invoice Solution/agent/sandbox/Invoice Solution-erd.mdTool call sequence: ls (1) → 3 parallel Reads (1) → analysis + present report (0) → ask developer (1) → generate + write (1) = 4 tool call rounds
User: "Extract the ERD for this solution"
ls agent/context/ → emptyautomation.json → OData config exists for the solution$metadata (single request contains all data)User: "Show me the ERD"
automation.json?"development
Generate a complete web application inside a FileMaker Web Viewer — self-contained HTML/CSS/JS styled with the FM theme, plus companion FM bridge scripts for bidirectional data flow. Use when the developer says "web viewer", "webviewer app", "HTML in FileMaker", "build web viewer", or when the layout-design skill delegates to the web-first output path. Recommended for modern, responsive UI, complex interactions (drag-and-drop, charts, rich text), or solutions considering future migration off FileMaker.
development
Trace references to a FileMaker object across the entire solution. Supports usage reports ("where is this field used?"), impact analysis ("what breaks if I rename this?"), and dead object scans ("show unused fields/scripts"). Use when the developer says "trace", "find references", "where is X used", "impact of renaming", "unused fields/scripts", "dead code", "what references X", or "is X used anywhere".
development
Analyze a FileMaker solution and produce a structured profile covering data model, business logic, UI layer, integrations, and health metrics. Uses on-disk pre-processing to handle solutions of any size without sending raw XML through the agent. Use when the developer says "analyze solution", "solution overview", "solution analysis", "solution profile", "solution spec", "what does this solution do", "solution summary", or wants a high-level understanding of an entire FileMaker solution.
development
Interactive setup wizard for agentic-fm. Detects what's already configured, walks the user through each remaining step, and verifies completion before proceeding. Use when the developer says "help me set up", "setup", "get started", "onboard", "first time setup", "install agentic-fm", "configure agentic-fm", or is clearly new to the project and needs guidance.