一键导入
database-migrations
Create and manage PostgreSQL database migrations. Use when adding tables, columns, indexes, or modifying the database schema.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Create and manage PostgreSQL database migrations. Use when adding tables, columns, indexes, or modifying the database schema.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
Diagnose and fix Shorted web performance (Core Web Vitals, bundle size, Lighthouse/PageSpeed) and keep it from regressing. Use when a PageSpeed/Lighthouse report comes in, LCP/TBT/CLS is high, the JS bundle grows, images are heavy, or someone asks to "make the site faster" / "improve the score".
Operate and improve the Shorted weekly/monthly/yearly short-selling report pipeline — run the generator, iterate on prompts safely, debug quality-gate failures, extend the data snapshot, and keep the generator↔proto JSON contract intact. Use when generating/regenerating reports, tuning report prompts, adding fields to the report snapshot, or debugging /reports pages.
Operate and improve the Shorted investigative newsroom — generate, validate, publish, and iterate on MDX editorial takes. Use when running newsroom-daily/preview, regenerating images, fixing article quality, extending the MDX component palette, or debugging duplicates in the wire feed.
Compose and post full-stack social posts to @shorted___ on X — text + X-card link preview + generated infographic. Wraps the Twitter bot, /api/og/twitter PNG endpoint, and /news/[slug] editorial pages. Use when the user says "post a tweet", "tweet today's shorts", "share to X", "social post", "compose a tweet about $TICKER", or "/social-post".
Add new Connect-RPC API endpoints to the shorts backend. Use when creating new API methods, defining protobuf services, or implementing backend handlers.
Manage data population and synchronization for ASIC short data and stock prices. Use when populating the database, syncing data, or troubleshooting data issues.
| name | database-migrations |
| description | Create and manage PostgreSQL database migrations. Use when adding tables, columns, indexes, or modifying the database schema. |
| allowed-tools | Read, Write, Bash(make:*), Bash(psql:*), Grep, Glob |
This skill guides you through creating and managing database migrations for the Shorted project.
# Create a new migration
cd services && make migrate-create NAME=add_users_table
# Apply pending migrations
cd services && make migrate-up
# Rollback last migration
cd services && make migrate-down
# Check current version
cd services && make migrate-version
Migrations are stored in services/migrations/ with sequential numbering:
services/migrations/
├── 000001_init_schema.up.sql
├── 000001_init_schema.down.sql
├── 000002_add_company_metadata.up.sql
├── 000002_add_company_metadata.down.sql
└── ...
cd services
make migrate-create NAME=add_user_watchlists
This creates two files:
XXXXXX_add_user_watchlists.up.sql - Forward migrationXXXXXX_add_user_watchlists.down.sql - Rollback migration-- services/migrations/XXXXXX_add_user_watchlists.up.sql
-- Create the watchlists table
CREATE TABLE IF NOT EXISTS user_watchlists (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id TEXT NOT NULL,
name TEXT NOT NULL DEFAULT 'My Watchlist',
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
-- Create the watchlist items table
CREATE TABLE IF NOT EXISTS watchlist_items (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
watchlist_id UUID NOT NULL REFERENCES user_watchlists(id) ON DELETE CASCADE,
stock_code TEXT NOT NULL,
added_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
notes TEXT,
UNIQUE(watchlist_id, stock_code)
);
-- Add indexes for common queries
CREATE INDEX idx_user_watchlists_user_id ON user_watchlists(user_id);
CREATE INDEX idx_watchlist_items_watchlist_id ON watchlist_items(watchlist_id);
CREATE INDEX idx_watchlist_items_stock_code ON watchlist_items(stock_code);
-- Add trigger for updated_at
CREATE OR REPLACE FUNCTION update_updated_at_column()
RETURNS TRIGGER AS $$
BEGIN
NEW.updated_at = NOW();
RETURN NEW;
END;
$$ language 'plpgsql';
CREATE TRIGGER update_user_watchlists_updated_at
BEFORE UPDATE ON user_watchlists
FOR EACH ROW
EXECUTE FUNCTION update_updated_at_column();
-- services/migrations/XXXXXX_add_user_watchlists.down.sql
-- Drop in reverse order of creation
DROP TRIGGER IF EXISTS update_user_watchlists_updated_at ON user_watchlists;
DROP FUNCTION IF EXISTS update_updated_at_column();
DROP INDEX IF EXISTS idx_watchlist_items_stock_code;
DROP INDEX IF EXISTS idx_watchlist_items_watchlist_id;
DROP INDEX IF EXISTS idx_user_watchlists_user_id;
DROP TABLE IF EXISTS watchlist_items;
DROP TABLE IF EXISTS user_watchlists;
-- Up
ALTER TABLE shorts ADD COLUMN source TEXT DEFAULT 'asic';
-- Down
ALTER TABLE shorts DROP COLUMN IF EXISTS source;
-- Up
CREATE INDEX CONCURRENTLY idx_shorts_date_product
ON shorts("DATE", "PRODUCT_CODE");
-- Down
DROP INDEX CONCURRENTLY IF EXISTS idx_shorts_date_product;
-- Up
ALTER TABLE "company-metadata" RENAME COLUMN old_name TO new_name;
-- Down
ALTER TABLE "company-metadata" RENAME COLUMN new_name TO old_name;
-- Up
ALTER TABLE stock_prices
ADD CONSTRAINT fk_stock_prices_stock_code
FOREIGN KEY (stock_code) REFERENCES stocks(code);
-- Down
ALTER TABLE stock_prices
DROP CONSTRAINT IF EXISTS fk_stock_prices_stock_code;
Host: localhost:5438
Database: shorts
Username: admin
Password: password
# Connect directly
psql postgresql://admin:password@localhost:5438/shorts
# Or use make target
make dev-db # Ensure database is running first
Production migrations require the DATABASE_URL environment variable:
export DATABASE_URL='postgresql://user:pass@host:5432/database'
cd services && make migrate-up-prod
# Start the database
make dev-db
# Apply migration
cd services && make migrate-up
# Verify tables exist
psql postgresql://admin:password@localhost:5438/shorts -c "\dt"
# Test rollback
cd services && make migrate-down
# Re-apply
cd services && make migrate-up
cd services && make migrate-version
IF EXISTS / IF NOT EXISTS for idempotencyCONCURRENTLY for index creation on large tablesDELETE or UPDATE - use explicit transactions# Force set version (use with caution!)
cd services && make migrate-force VERSION=X
If a migration failed partway through:
# Check current state
cd services && make migrate-version
# Force to last known good version
cd services && make migrate-force VERSION=X
# Then retry
cd services && make migrate-up
SELECT * FROM schema_migrations ORDER BY version;