Skills DirectorySkills Directory
SkillsLearnSecurityCategoriesDocsBlogPro
Sign InSubmit Skill
Skills Directory

Security-tested agent skills for Claude, coding agents, and AI workflows.

Directory

  • Browse Skills
  • All Skills A–Z
  • Claude Skills
  • Claude Code Skills
  • Agent Skills
  • Categories
  • Authors
  • Submit a Skill

Learn

  • Learn Hub
  • Install Claude Skills
  • Write SKILL.md
  • Skills vs MCP
  • Directories Compared

Security

  • Security
  • Methodology
  • Secure Claude Skills
  • Security Badges
  • Chrome Extension
  • Skill Manager

Company

  • About
  • Community
  • Blog
  • API Docs
  • Advertise

2026 Skills Directory. All rights reserved.

ProTermsPrivacyRefunds
Back to skills

Map Data

ASecurity

Draw an entity-relationship diagram from committed schema declarations, with no database connection. Prisma models win over a stated subset of Entity Framework fluent mappings, which win over SQL migrations read from a stated subset of statements, and a disagreement is reported. Use when: 'map data', 'ERD', 'entity relationship', 'schema diagram', 'cardinality from mappings', 'which tables relate'. Skip when: the question is deployment topology, runtime state, or data volume.

20 stars
0 votes
0 copies
0 views
Added 9/29/2026
ai-agentsgoshellbashsqlnodeexpressdjangogitdatabase

Works with

cli

Security Analysis

A100/100

Pro scans all 5 files and shows the line behind each finding

Scanned 10/4/2026

$npx -y skills add melodic-software/claude-code-plugins --skill map-data --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Map Data?

Add the live security badge to your README — it updates automatically with every re-scan.

Security grade badge for Map Data
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/melodic-software-map-data/badge)](https://www.skillsdirectory.com/skills/melodic-software-map-data)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
Files
SKILL.md
---
description: "Draw an entity-relationship diagram from committed schema declarations, with no database connection. Prisma models win over a stated subset of Entity Framework fluent mappings, which win over SQL migrations read from a stated subset of statements, and a disagreement is reported. Use when: 'map data', 'ERD', 'entity relationship', 'schema diagram', 'cardinality from mappings', 'which tables relate'. Skip when: the question is deployment topology, runtime state, or data volume."
argument-hint: "[--scope module|all|<module>] [--include-columns] [--dialect mermaid|dbml] [--out <dir>]"
user-invocable: true
disable-model-invocation: false
shell: bash
metadata:
  workflow-stage: explore
  summary: Draw an ERD from a committed schema, offline
---

## Repository context

The current repository is both the CONSUMER, whose convention home declares where artifacts land,
and the DEFAULT SUBJECT, the repository whose tracked files declare the schema.

Collect with an **individual** Bash call, one command per call: the project root,
`git rev-parse --show-toplevel`. Treat a failure (not a repository, git unavailable) as an unknown
value and carry on; `${CLAUDE_PROJECT_DIR}` is the resolver's `--root` either way.

## Purpose

Answer "what are the entities and how do they relate" from declarations already in the tree. Every
entity and every cardinality traces to a named file. The scripts collect and render. Do not draw a
box the script did not emit, and do not invent a cardinality the script did not record.

This is not a C4 diagram. The C4 set is system context, containers, components, and code, plus
system landscape, dynamic, and deployment. An entity-relationship diagram is none of those.

## Resolve home and dialect

Read `${CLAUDE_PLUGIN_ROOT}/reference/config.md` first. This skill writes into `architecture_dir`.
It does not read `landscape_dialect` and it does not add a dialect key. The diagram dialect is
`diagram_dialect.data` from the authoring-formats topic doc.

Run `bash "${CLAUDE_PLUGIN_ROOT}/lib/resolve-convention-home.sh" --root "${CLAUDE_PROJECT_DIR}"` and
follow the exit code. Never parse the root instruction file yourself. Exit 0 means read
`<home>/architecture/README.md` for `architecture_dir`. Exit 1, 2, and 3 mean there is no declared
home.

Per key, in order: `--out <dir>` wins for this run alone, then a declared `architecture_dir`, then
one question. `architecture_dir` has NO default. An undeclared and unconfirmed home, including
every non-interactive run, STOPS and points at `/architecture:setup`. Do not invent a directory.

Resolve `diagram_dialect.data` by restating this ladder, then running the resolver rather than
parsing the topic doc yourself. The ladder is a resolution order, not a task list:

```markdown
1. Anchor at the repository root: `${CLAUDE_PROJECT_DIR}` when set, otherwise
   `git rev-parse --show-toplevel`. Never a CWD-relative read.
2. Resolve the convention home `<home>` with the bundled resolver above. Never hand-parse the root
   file.
3. The printed home is repo-relative: join it to the root, then pass
   `<root>/<home>/authoring-formats/README.md` to the resolver.
4. Layer order is one layer deep: an explicit `--dialect` argument, then the team convention doc,
   then the documented default `mermaid`. There is no personal overlay.
5. Default: `diagram_dialect.data` is `mermaid`. Allowed values are `mermaid` and `dbml`.
6. Degrade soft, and say so. No pointer, no doc, no key, or an unrecognized value each resolve to
   `mermaid`. The resolver names the cause on stderr. Do not hard-fail and do not ask the operator
   to create the surface mid-task.
7. Report provenance: the key, the value, and the layer (`argument`, `team convention doc <path>`,
   or `default`).
```

```bash
bash "${CLAUDE_PLUGIN_ROOT}/lib/resolve-diagram-dialect.sh" --kind data \
  --formats "<root>/<home>/authoring-formats/README.md"
```

Omit `--formats` when no convention home resolved. Stdout is `mermaid` or `dbml`. An explicit
`--dialect` on the invocation wins and the resolver is not required.

This skill never writes the consumer's root instruction file or its topic doc.

## Build the record

```bash
"${CLAUDE_SKILL_DIR}/scripts/collect-data.sh" \
  --repo "<subject-repo>" --out "<architecture_dir>/data-model.json" \
  --generated-on "<YYYY-MM-DD|unknown>"
```

Pass `--generated-on` from `git -C <root> log -1 --format=%cs`, or `unknown` when that fails.
Pass `--live` only when the invocation asked for a live connection. The script does not open one.
It writes a refusal and does not read the schema.

The record is schema_version 1, one object per line. `status` is `drawn` or `refused`. A refusal
names `reason` and writes no relationships. Shipped tiers, first present wins the diagram:

- **model / prisma.** `*.prisma` model blocks.
- **orm / ef-fluent.** A stated subset of one-to-many and one-to-one chains. The chain starts at
  `Entity<T>()` or, in a file that declares exactly one `class X : IEntityTypeConfiguration<T>`
  (also among several base types), at the `Configure` builder parameter. `HasOne`/`HasMany` take a
  generic argument or, for one-to-many, a lambda navigation (`HasMany(e => e.Posts).WithOne(e => e.Blog)`,
  `HasOne(e => e.Blog).WithMany(e => e.Posts)`); the navigation's target comes from the property
  declared on the configured entity's class in the scanned `.cs` files (`ICollection`, `List`,
  `IList`, `IEnumerable` or `HashSet` of one identifier for a collection, `T` or `T?` for a
  reference). `HasForeignKey` and `HasPrincipalKey` take one string literal or one single-member
  lambda. Requiredness is an explicit `IsRequired()`, `IsRequired(true)` or `IsRequired(false)`; with none, it is the
  foreign-key property's declared type on the dependent class: `T?`, `Nullable<T>` and `string?`
  are optional, and `int`, `uint`, `long`, `ulong`, `short`, `ushort`, `byte`, `sbyte`, `Guid`,
  `DateTime` and `DateTimeOffset` are required.
- **migration / sql-migration.** `*.sql` under a `migrations` directory at any depth, including one
  at the repository root, replayed in path order. The readable statements are `CREATE TABLE`
  (with inline `REFERENCES`, table-level `FOREIGN KEY`, `UNIQUE` and `PRIMARY KEY`),
  `CREATE UNIQUE INDEX`, `DROP INDEX`, `DROP TABLE`, and `ALTER TABLE` with `ADD COLUMN`,
  `DROP COLUMN`, `ADD [CONSTRAINT n] FOREIGN KEY | UNIQUE | PRIMARY KEY`, and `DROP CONSTRAINT`
  naming a constraint the migrations declared. Any other `ALTER TABLE` action (`RENAME`,
  `ALTER COLUMN`, a `DROP CONSTRAINT` it cannot map) refuses the tier with `sql-alter-unreadable`.

A second shipped tier that disagrees becomes a mismatch row. The diagram stays on the winning tier.
A tier that loses and cannot be read (an EF chain outside the subset, an unreadable migration) does
not refuse the record: it is left out of the comparison and listed as a `not-compared` row.
Django models, SQLAlchemy columns, EF `[ForeignKey]` annotations, and a Prisma many-to-many with no
`fields:` list refuse the record (`partial-read` or a named reason), as does an EF chain outside the
subset when EF is the winning tier (`ef-fluent-unreadable`), a migration outside the subset when
SQL is the winning tier (`sql-alter-unreadable`), and a composite foreign key with no unique column
set inside it (`unknown-cardinality`). A shipped diagram beside an unread mechanism would be a
partial read.

A module is the first path segment of the declaring file, or `.` at the repository root. It is
listed only when the winning tier declares an entity in it.

## Render

```bash
"${CLAUDE_SKILL_DIR}/scripts/render-data.sh" \
  --record "<architecture_dir>/data-model.json" --out "<architecture_dir>" \
  --dialect "<mermaid|dbml>" --scope "<module|all|id>"
```

Add `--include-columns` only when the invocation asked for columns. The default scope is `module`:
one module is drawn; several modules write a refusal that lists them and the script exits 3. Draw
nothing until the operator passes `--scope <id>` or `--scope all`. In a non-interactive run, stop
after that refusal. Do not pick a module. With more than one module in scope, every node is named
`module/Entity`, so `orders/User` and `billing/User` stay two nodes.

Mermaid writes an `erDiagram` inside `data-model.md`. DBML writes `data-model.dbml` and points at
it from `data-model.md`. Column names and types appear in the diagram only with `--include-columns`.
The relationship list and the mismatch list are not a column dump.

The script prints one summary line. Keep it:

`data: status=<drawn|refused> reason=<reason|none> tier=<tier> tool=<tool> modules=<n> entities=<n> relationships=<n> mismatches=<n> columns=<yes|no> dialect=<mermaid|dbml> scope=<id|all|unresolved|none>`

Exit 1 means the record is unreadable or not schema_version 1 in the one-object-per-line layout.
Nothing was written. Report that message. Do not reformat the record by hand.

## Close with the report

End every run with this block, in this order:

- **Artifacts**: each path written, or `none written` when the run stopped before a home existed.
- **Status**: `drawn` or `refused`, and the reason when it is a refusal.
- **Source**: the tier and the tool, quoted from the summary, or `none` on a refusal.
- **Dialect**: `mermaid` or `dbml`, and the layer it came from.
- **Scope**: the module, `all`, or `unresolved` with the module list.
- **Columns**: omitted, or included.
- **Mismatches**: the count. A mismatch is reported, not silently resolved.
- **Live**: not requested, or requested and refused. No connection was opened.

## Interactive view

After the report, offer an interactive view of `data-model.json` in one sentence. The markdown and the record
stay authoritative. Build it only with `${CLAUDE_PLUGIN_ROOT}/scripts/build-view.mjs data`, never
hand-written; the publish destination comes from the `medium` cascade key. Procedure:
[`${CLAUDE_PLUGIN_ROOT}/reference/rendered-view.md`](${CLAUDE_PLUGIN_ROOT}/reference/rendered-view.md).

## What this skill does NOT do

- Open a database connection, read production data, or compare live rows to the declaration.
- Indexes, data volumes, query plans, lineage, or ETL.
- A C4 view, or a new dialect key. The dialect is the existing `diagram_dialect.data`.
- Adapters other than Prisma models, the EF fluent subset above, and the SQL statements listed
  above. Other mechanisms refuse. Within EF, these refuse: a composite key, `HasOne(lambda)` paired
  with `WithOne`, a navigation with no single declared type (an expression-bodied property, a
  positional record member, an undeclared name), two declarations of one class property in the
  same module, a file with zero or several `IEntityTypeConfiguration<T>` classes, an `IsRequired`
  argument other than `true` or `false`, and, when
  `IsRequired` is absent, a foreign key that is undeclared or has a plain `string`, enum or other
  type, because its nullability depends on the project's nullable setting. A `[ForeignKey]`
  annotation is not read.
- Guess a cardinality the declaration does not state. Implicit Prisma many-to-many and a composite
  foreign key with no unique column set refuse.
- Invent a home. No declared, no `--out`, and no confirmed `architecture_dir` is a stop.

## Next

- The schema settles a decision worth keeping: `/architecture:record-decision`.
- The question is which systems the repository sits among: `/architecture:map-landscape`.

## Gotchas

- **The picture is not a C4 diagram.** C4's diagrams are system context, containers, components,
  and code, plus system landscape, dynamic, and deployment. None of those is an
  entity-relationship diagram, so this skill adds no C4 dialect key and reads
  `diagram_dialect.data` (`mermaid` or `dbml`). Verified 2026-09-28 against <https://c4model.com/>.
  Recheck when that page adds a diagram type whose subject is entities and their relationships.
- **A Prisma one-to-many stores the foreign key on the many side.** The scalar named by
  `@relation(fields:, references:)` is the foreign key. The list side does not store a column.
  Required means both the relation field and the scalar omit `?`. Verified 2026-09-28 against
  <https://www.prisma.io/docs/orm/prisma-schema/data-model/relations/one-to-many-relations>.
  Recheck when that page stops using `fields` and `references` to name the foreign key.
- **The EF reader is a stated subset of the documented fluent chain.** The one-to-many page shows
  `HasMany`/`HasOne`, `WithOne`/`WithMany`, `HasForeignKey`, and `IsRequired`, including the lambda
  form, and the foreign-key page says the nullability of the foreign-key property determines
  whether a relationship is optional or required. A non-nullable navigation does not change that:
  a probe with EF Core 10.0.0 and nullable reference types on gave an optional relationship for
  `int? BlogId` with `Blog Blog = null!` and no `IsRequired`, and a required one for `int BlogId`.
  Verified 2026-09-29 against
  <https://learn.microsoft.com/en-us/ef/core/modeling/relationships/one-to-many> and
  <https://learn.microsoft.com/en-us/ef/core/modeling/relationships/foreign-and-principal-keys>.
  Recheck when either page changes how nullability sets requiredness, or on an EF Core major
  release. The script's stderr names the property or chain that stopped a refused read; the
  record's reason stays `ef-fluent-unreadable`. A declaration in the configuration file's own
  module is preferred over the rest of the repository. A chain outside the subset refuses the
  record only when EF is the winning tier. Beside a Prisma schema it is a `not-compared` row, so a
  test or sample file cannot block the diagram.
- **The SQL reader replays a stated subset.** It reads the statements listed under the tiers and
  refuses the tier with `sql-alter-unreadable` on any other `ALTER TABLE` action, because a renamed
  table or a changed column would leave the replayed shape wrong. A migration it cannot read never
  produces a mismatch claim against the winning tier.
- **Two modules can declare the same short name.** Nodes are keyed by module and name. The
  diagram names a node `module/Entity` whenever more than one module is in scope, quoted in
  Mermaid (`"orders/User"`) because an unquoted name with a slash does not parse. Verified
  2026-09-29 by parsing both forms with mermaid 12.0.0 and against
  <https://mermaid.js.org/syntax/entityRelationshipDiagram.html> (entity names in double quotes).
  Recheck when that page changes its rule for entity names.
- **A required relationship does not mean the principal has at least one dependent.** The diagram
  uses `||--o{` for a required foreign key. That matches both Prisma and EF: the many side may be
  empty. The same EF page states there is no standard way to require a minimum number of
  dependents. Do not draw `||--|{` from a required foreign key.
- **A foreign key covered by a unique column set is one-to-one, drawn `||--o|` or `|o--o|`.** The
  referenced entity is on the left, so `||` says each dependent row names exactly one principal,
  and `o|` says the principal has zero or one dependent. A required unique foreign key is
  `||--o|`; an optional one is `|o--o|`. Never `||--||`, which would demand a dependent for every
  principal. Uniqueness is a Prisma `@unique`, `@id`, `@@unique([..])` or `@@id([..])`, or a SQL
  `UNIQUE`, `PRIMARY KEY`, `CREATE UNIQUE INDEX` or `ALTER TABLE ... ADD UNIQUE`, whose columns
  lie inside the foreign-key columns. A composite foreign key with no such set has no readable
  cardinality, so the record refuses with `unknown-cardinality` rather than drawing one-to-many.
  Verified 2026-09-29 against <https://mermaid.js.org/syntax/entityRelationshipDiagram.html> (`|o`
  and `o|` zero or one, `||` exactly one, `o{` zero or more) and
  <https://www.prisma.io/docs/orm/prisma-schema/data-model/relations/one-to-one-relations> (a 1-1
  relation needs a `UNIQUE` constraint on the foreign key). Recheck when either page changes its
  markers or its uniqueness rule.
- **DBML names the referenced column the declaration names.** Prisma `references: [..]` and SQL
  `REFERENCES t(col)` fill it, and EF `HasPrincipalKey("Col")` does. Where the declaration names
  none, the `Ref` becomes a `//` comment that says so, because DBML needs a column on both sides;
  the script never assumes `id`.
- **A reformatted record reads as empty unless the reader refuses it.** Render exits 1 on any
  layout other than one object per line and writes nothing.
- **Tracked files only.** `git ls-files` is the source list. An untracked schema is not a
  declaration. A directory that is not a git repository is a refusal.
- **`--live` is a refusal.** No connection string is read and no client is invoked. Offline tiers
  are not silently substituted.
- **Two mechanisms are not half-read.** Django, SQLAlchemy, and EF data annotations are recognized
  and then the run stops, even when a Prisma schema is also present.

Attribution

melodic-softwaremelodic-software
View sourceSee grades on GitHubMore from melodic-software →
SSkills DirectorySkills Directory

Ship a skill? Prove it's safe.

Free 120-pattern security scan, letter grade, and an embeddable README badge.

Submit a skill

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments (0)

No comments yet. Be the first to comment!

SSkills DirectorySkills Directory

Ship a skill? Prove it's safe.

Free 120-pattern security scan, letter grade, and an embeddable README badge.

Submit a skill

Related Skills

Caveman

Terse caveman voice: answer first, fluff gone, every technical fact kept. Use for /caveman, "caveman mode", "talk like caveman", "be brief", "less tokens". Stays on until "stop caveman" or "normal mode".

1100021 votes

Hyperplan

Adversarial multi-agent planning skill. Self-orchestrates 5 hostile category members (unspecified-low, unspecified-high, deep, ultrabrain, artistry) via team-mode for ruthless cross-critique debate, distills only the defensible insights, then MANDATORILY hands the distilled insight bundle to the `plan` agent for executable plan formalization. Use when planning needs maximum rigor and surfacing of weak assumptions, blind spots, and over-engineering. Triggers: 'hyperplan', 'hpp', '/hyperplan', ...

698621 votes

Writing Skills

Create and manage Claude Code skills in HASH repository following Anthropic best practices. Use when creating new skills, modifying skill-rules.json, understanding trigger patterns, working with hooks, debugging skill activation, or implementing progressive disclosure. Covers skill structure, YAML frontmatter, trigger types (keywords, intent patterns), UserPromptSubmit hook, and the 500-line rule. Includes validation and debugging with SKILL_DEBUG. Examples include rust-error-stack, cargo-dep...

3931 votes

Mcp Code Execution

Routes multi-tool workflows through MCP servers for large datasets and pipelines. Use when Bash tool overhead is limiting throughput on data-heavy tasks.

3421 votes

catchup

Recovers the conversation and failed tool calls of a previous Codex, Amp, Claude Code, Antigravity, Cline, Copilot CLI, Cursor, DeepSeek Harness, Grok Build, Kimi, OpenCode, Pi Agent, or ZCode session. Use when the user says "catch up", "what did the last session do", "get me up to speed", "I switched agents", asks to recover/summarize a previous session before continuing, or asks to diagnose or report a catchup failure. Do NOT use for the current conversation, git history, or any non-agent log.

741 votes
View all in ai-agents →