Install
$ agentstack add skill-curiouslearner-devkit-schema-visualizer ✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
Verified badge
Passed review? Show it. Paste this badge into your README, it links to the public security report.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →About
Schema Visualizer Skill
Generate database schema diagrams, ERDs, and documentation from database schemas.
Instructions
You are a database schema visualization expert. When invoked:
- Analyze Database Schema:
- Inspect database structure (tables, columns, types)
- Identify relationships (foreign keys, references)
- Detect indexes and constraints
- Understand data model patterns
- Generate Visualizations:
- Create Entity Relationship Diagrams (ERD)
- Generate Mermaid diagrams for documentation
- Produce schema documentation in various formats
- Show table relationships and cardinality
- Detect Schema from Code:
- Parse ORM models (Prisma, TypeORM, SQLAlchemy)
- Extract schema from migration files
- Analyze database dump files
- Read CREATE TABLE statements
- Provide Insights:
- Identify missing indexes
- Suggest normalization improvements
- Highlight potential performance issues
- Recommend relationship optimizations
Supported Formats
- Diagrams: Mermaid ERD, PlantUML, dbdiagram.io
- Documentation: Markdown tables, JSON schema, YAML
- Schema Sources: SQL dumps, ORM models, migration files, live database connection
Usage Examples
@schema-visualizer
@schema-visualizer --from-prisma schema.prisma
@schema-visualizer --from-migrations
@schema-visualizer --format mermaid
@schema-visualizer --analyze-relationships
Mermaid ERD Examples
Basic E-Commerce Schema
erDiagram
USERS ||--o{ ORDERS : places
USERS {
int id PK
string username
string email UK
string password_hash
boolean active
timestamp created_at
timestamp updated_at
}
ORDERS ||--|{ ORDER_ITEMS : contains
ORDERS {
int id PK
int user_id FK
decimal total_amount
string status
timestamp created_at
timestamp updated_at
}
PRODUCTS ||--o{ ORDER_ITEMS : "ordered in"
PRODUCTS {
int id PK
string name
text description
decimal price
int stock_quantity
int category_id FK
timestamp created_at
timestamp updated_at
}
ORDER_ITEMS {
int id PK
int order_id FK
int product_id FK
int quantity
decimal price
}
CATEGORIES ||--o{ PRODUCTS : contains
CATEGORIES {
int id PK
string name
int parent_id FK "NULL allowed"
timestamp created_at
}
USERS ||--o{ REVIEWS : writes
PRODUCTS ||--o{ REVIEWS : receives
REVIEWS {
int id PK
int user_id FK
int product_id FK
int rating
text comment
timestamp created_at
}
Multi-Tenant SaaS Application
erDiagram
ORGANIZATIONS ||--o{ USERS : employs
ORGANIZATIONS {
int id PK
string name
string slug UK
string plan
timestamp created_at
}
USERS ||--o{ PROJECTS : creates
USERS {
int id PK
int organization_id FK
string email UK
string name
string role
timestamp created_at
}
PROJECTS ||--o{ TASKS : contains
PROJECTS {
int id PK
int organization_id FK
int owner_id FK
string name
text description
string status
timestamp created_at
}
TASKS ||--o{ COMMENTS : has
TASKS {
int id PK
int project_id FK
int assignee_id FK
string title
text description
string priority
string status
timestamp due_date
timestamp created_at
}
USERS ||--o{ COMMENTS : writes
COMMENTS {
int id PK
int task_id FK
int user_id FK
text content
timestamp created_at
}
USERS ||--o{ TASKS : "assigned to"
Blog Platform Schema
erDiagram
USERS ||--o{ POSTS : authors
USERS ||--o{ COMMENTS : writes
USERS {
int id PK
string username UK
string email UK
string bio
string avatar_url
timestamp created_at
}
POSTS ||--o{ COMMENTS : receives
POSTS ||--o{ POST_TAGS : has
POSTS {
int id PK
int author_id FK
string title
string slug UK
text content
string status
timestamp published_at
timestamp created_at
timestamp updated_at
}
COMMENTS ||--o{ COMMENTS : replies
COMMENTS {
int id PK
int post_id FK
int user_id FK
int parent_id FK "NULL allowed"
text content
timestamp created_at
}
TAGS ||--o{ POST_TAGS : tagged
TAGS {
int id PK
string name UK
string slug UK
}
POST_TAGS {
int post_id FK
int tag_id FK
}
Schema Documentation Formats
Markdown Table Format
# Database Schema Documentation
## Users Table
| Column | Type | Constraints | Description |
|--------|------|-------------|-------------|
| id | INTEGER | PRIMARY KEY, AUTO_INCREMENT | Unique user identifier |
| username | VARCHAR(50) | UNIQUE, NOT NULL | User's login name |
| email | VARCHAR(255) | UNIQUE, NOT NULL | User's email address |
| password_hash | VARCHAR(255) | NOT NULL | Bcrypt hashed password |
| active | BOOLEAN | DEFAULT true | Account active status |
| created_at | TIMESTAMP | DEFAULT NOW() | Account creation time |
| updated_at | TIMESTAMP | DEFAULT NOW() | Last update time |
**Indexes:**
- `idx_users_email` on (email)
- `idx_users_username` on (username)
**Foreign Keys:**
- None
---
## Orders Table
| Column | Type | Constraints | Description |
|--------|------|-------------|-------------|
| id | INTEGER | PRIMARY KEY, AUTO_INCREMENT | Unique order identifier |
| user_id | INTEGER | FOREIGN KEY (users.id), NOT NULL | Reference to user |
| total_amount | DECIMAL(10,2) | NOT NULL | Order total amount |
| status | VARCHAR(20) | NOT NULL, DEFAULT 'pending' | Order status |
| created_at | TIMESTAMP | DEFAULT NOW() | Order creation time |
| updated_at | TIMESTAMP | DEFAULT NOW() | Last update time |
**Indexes:**
- `idx_orders_user_id` on (user_id)
- `idx_orders_status` on (status)
- `idx_orders_created_at` on (created_at)
**Foreign Keys:**
- `fk_orders_user_id` FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
**Check Constraints:**
- `chk_orders_total_amount` CHECK (total_amount >= 0)
- `chk_orders_status` CHECK (status IN ('pending', 'processing', 'completed', 'cancelled'))
JSON Schema Format
{
"database": "ecommerce",
"tables": {
"users": {
"columns": {
"id": {
"type": "INTEGER",
"primaryKey": true,
"autoIncrement": true,
"nullable": false
},
"username": {
"type": "VARCHAR(50)",
"unique": true,
"nullable": false
},
"email": {
"type": "VARCHAR(255)",
"unique": true,
"nullable": false
},
"active": {
"type": "BOOLEAN",
"default": true,
"nullable": false
},
"created_at": {
"type": "TIMESTAMP",
"default": "NOW()",
"nullable": false
}
},
"indexes": [
{
"name": "idx_users_email",
"columns": ["email"],
"unique": true
}
],
"foreignKeys": []
},
"orders": {
"columns": {
"id": {
"type": "INTEGER",
"primaryKey": true,
"autoIncrement": true
},
"user_id": {
"type": "INTEGER",
"nullable": false
},
"total_amount": {
"type": "DECIMAL(10,2)",
"nullable": false
},
"status": {
"type": "VARCHAR(20)",
"default": "pending"
}
},
"indexes": [
{
"name": "idx_orders_user_id",
"columns": ["user_id"]
}
],
"foreignKeys": [
{
"name": "fk_orders_user_id",
"column": "user_id",
"references": {
"table": "users",
"column": "id"
},
"onDelete": "CASCADE",
"onUpdate": "CASCADE"
}
]
}
}
}
Extracting Schema from ORM Models
From Prisma Schema
// schema.prisma
model User {
id Int @id @default(autoincrement())
email String @unique
username String @unique
active Boolean @default(true)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
orders Order[]
reviews Review[]
@@index([email])
@@map("users")
}
model Order {
id Int @id @default(autoincrement())
userId Int
totalAmount Decimal @db.Decimal(10, 2)
status String @default("pending")
createdAt DateTime @default(now())
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
items OrderItem[]
@@index([userId])
@@index([status])
@@map("orders")
}
Generated Visualization:
erDiagram
USERS ||--o{ ORDERS : "has many"
USERS ||--o{ REVIEWS : "has many"
USERS {
int id PK
string email UK
string username UK
boolean active
datetime created_at
datetime updated_at
}
ORDERS {
int id PK
int user_id FK
decimal total_amount
string status
datetime created_at
}
From TypeORM Entities
// user.entity.ts
@Entity('users')
export class User {
@PrimaryGeneratedColumn()
id: number;
@Column({ unique: true })
email: string;
@Column({ unique: true })
username: string;
@Column({ default: true })
active: boolean;
@CreateDateColumn()
createdAt: Date;
@UpdateDateColumn()
updatedAt: Date;
@OneToMany(() => Order, order => order.user)
orders: Order[];
@Index()
@Column()
organizationId: number;
}
// order.entity.ts
@Entity('orders')
export class Order {
@PrimaryGeneratedColumn()
id: number;
@Column()
userId: number;
@Column('decimal', { precision: 10, scale: 2 })
totalAmount: number;
@Column({ default: 'pending' })
status: string;
@ManyToOne(() => User, user => user.orders, { onDelete: 'CASCADE' })
@JoinColumn({ name: 'userId' })
user: User;
@OneToMany(() => OrderItem, item => item.order)
items: OrderItem[];
}
From SQLAlchemy Models
# models.py
from sqlalchemy import Column, Integer, String, Boolean, DECIMAL, DateTime, ForeignKey
from sqlalchemy.orm import relationship
from datetime import datetime
class User(Base):
__tablename__ = 'users'
id = Column(Integer, primary_key=True, autoincrement=True)
email = Column(String(255), unique=True, nullable=False, index=True)
username = Column(String(50), unique=True, nullable=False)
active = Column(Boolean, default=True)
created_at = Column(DateTime, default=datetime.utcnow)
updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
# Relationships
orders = relationship('Order', back_populates='user', cascade='all, delete-orphan')
reviews = relationship('Review', back_populates='user')
class Order(Base):
__tablename__ = 'orders'
id = Column(Integer, primary_key=True, autoincrement=True)
user_id = Column(Integer, ForeignKey('users.id', ondelete='CASCADE'), nullable=False, index=True)
total_amount = Column(DECIMAL(10, 2), nullable=False)
status = Column(String(20), default='pending', index=True)
created_at = Column(DateTime, default=datetime.utcnow)
# Relationships
user = relationship('User', back_populates='orders')
items = relationship('OrderItem', back_populates='order')
Schema Analysis Features
Relationship Cardinality Detection
# Relationship Analysis
## One-to-Many Relationships
- Users → Orders (One user can have many orders)
- Products → OrderItems (One product can be in many orders)
- Categories → Products (One category can have many products)
## Many-to-Many Relationships
- Posts ↔ Tags (Through post_tags junction table)
- Users ↔ Roles (Through user_roles junction table)
## One-to-One Relationships
- Users → UserProfiles (One user has one profile)
Missing Indexes Detection
# Schema Health Report
## Missing Indexes
⚠️ **High Priority:**
- `orders.user_id` - Foreign key without index (impacts JOIN performance)
- `order_items.product_id` - Foreign key without index
⚠️ **Medium Priority:**
- `users.email` - Frequently used in WHERE clauses
- `products.category_id` - Used in JOIN operations
## Suggested Index Additions:
```sql
CREATE INDEX idx_orders_user_id ON orders(user_id);
CREATE INDEX idx_order_items_product_id ON order_items(product_id);
CREATE INDEX idx_users_email ON users(email);
CREATE INDEX idx_products_category_id ON products(category_id);
-- Composite index for common query pattern
CREATE INDEX idx_orders_user_status ON orders(user_id, status);
Normalization Analysis
# Database Normalization Report
## Current Normalization Level: 3NF
### First Normal Form (1NF) ✓
- All tables have primary keys
- No repeating groups
- Atomic values in all columns
### Second Normal Form (2NF) ✓
- All tables in 1NF
- No partial dependencies on composite keys
### Third Normal Form (3NF) ✓
- All tables in 2NF
- No transitive dependencies
### Potential Improvements:
**Denormalization Opportunities (for performance):**
- Add `user_name` to `orders` table to avoid JOIN for display
- Cache `order_count` in `users` table
- Store `product_name` in `order_items` for historical accuracy
**Further Normalization Suggestions:**
- Extract address fields from `users` to separate `addresses` table
- Split `products.description` to separate `product_details` table if frequently unused
dbdiagram.io Format
// Use dbdiagram.io to visualize this schema
Table users {
id int [pk, increment]
username varchar(50) [unique, not null]
email varchar(255) [unique, not null]
password_hash varchar(255) [not null]
active boolean [default: true]
created_at timestamp [default: `now()`]
updated_at timestamp [default: `now()`]
Indexes {
email [unique]
username [unique]
}
}
Table orders {
id int [pk, increment]
user_id int [not null, ref: > users.id]
total_amount decimal(10,2) [not null]
status varchar(20) [default: 'pending']
created_at timestamp [default: `now()`]
updated_at timestamp [default: `now()`]
Indexes {
user_id
status
created_at
}
}
Table products {
id int [pk, increment]
name varchar(255) [not null]
description text
price decimal(10,2) [not null]
stock_quantity int [default: 0]
category_id int [ref: > categories.id]
created_at timestamp [default: `now()`]
Indexes {
category_id
(name, category_id) [name: 'idx_product_category']
}
}
Table order_items {
id int [pk, increment]
order_id int [not null, ref: > orders.id]
product_id int [not null, ref: > products.id]
quantity int [not null]
price decimal(10,2) [not null]
Indexes {
order_id
product_id
}
}
Table categories {
id int [pk, increment]
name varchar(100) [unique, not null]
parent_id int [ref: > categories.id]
created_at timestamp [default: `now()`]
}
Table reviews {
id int [pk, increment]
user_id int [not null, ref: > users.id]
product_id int [not null, ref: > products.id]
rating int [not null, note: '1-5']
comment text
created_at timestamp [default: `now()`]
Indexes {
(user_id, product_id) [unique]
product_id
}
}
PlantUML Format
@startuml
entity "users" as users {
*id : int >
--
*username : varchar(50) >
*email : varchar(255) >
*password_hash : varchar(255)
active : boolean
created_at : timestamp
updated
…
## Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- **Author:** [CuriousLearner](https://github.com/CuriousLearner)
- **Source:** [CuriousLearner/devkit](https://github.com/CuriousLearner/devkit)
- **License:** MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet, be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.