一键导入
database-operations
SQLite database patterns and SQLx usage in Rivetr. Use when writing database queries, debugging schema issues, or understanding data models.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
SQLite database patterns and SQLx usage in Rivetr. Use when writing database queries, debugging schema issues, or understanding data models.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
React Router v7, React Query, and shadcn/ui patterns used in the Rivetr dashboard. Use when writing new frontend components, routes, or API integrations.
Generate a Product Requirements Document (PRD) for a new feature. Use when planning a feature, starting a new project, or creating a PRD.
Convert PRDs to prd.json format for the Ralph autonomous agent system.
Test Rivetr REST API endpoints. Use when testing API functionality, debugging webhook issues, or verifying deployments.
Debug and understand the Rivetr deployment pipeline. Use when troubleshooting deployment failures, understanding pipeline stages, or working on engine code.
Test Docker and Podman container operations for Rivetr. Use when debugging container builds, testing runtime detection, or troubleshooting deployment issues.
| name | database-operations |
| description | SQLite database patterns and SQLx usage in Rivetr. Use when writing database queries, debugging schema issues, or understanding data models. |
| allowed-tools | Read, Grep, Glob, Bash |
Rivetr uses SQLite with SQLx for all persistent storage:
data/rivetr.dbuse sqlx::sqlite::{SqlitePool, SqlitePoolOptions};
// From src/db/mod.rs
pub async fn init_db(data_dir: &Path) -> Result<SqlitePool> {
let db_path = data_dir.join("rivetr.db");
let url = format!("sqlite:{}?mode=rwc", db_path.display());
let pool = SqlitePoolOptions::new()
.max_connections(5)
.connect(&url)
.await?;
// Enable WAL mode
sqlx::query("PRAGMA journal_mode = WAL")
.execute(&pool)
.await?;
Ok(pool)
}
let app = sqlx::query_as::<_, App>("SELECT * FROM apps WHERE id = ?")
.bind(&id)
.fetch_one(&pool)
.await?; // Errors if not found
let app = sqlx::query_as::<_, App>("SELECT * FROM apps WHERE id = ?")
.bind(&id)
.fetch_optional(&pool)
.await?; // Returns Option<App>
let apps = sqlx::query_as::<_, App>("SELECT * FROM apps ORDER BY created_at DESC")
.fetch_all(&pool)
.await?; // Returns Vec<App>
sqlx::query(
"INSERT INTO apps (id, name, git_url, branch, port, created_at, updated_at)
VALUES (?, ?, ?, ?, ?, ?, ?)"
)
.bind(&app.id)
.bind(&app.name)
.bind(&app.git_url)
.bind(&app.branch)
.bind(app.port)
.bind(&app.created_at)
.bind(&app.updated_at)
.execute(&pool)
.await?;
sqlx::query("UPDATE apps SET name = ?, updated_at = ? WHERE id = ?")
.bind(&name)
.bind(Utc::now())
.bind(&id)
.execute(&pool)
.await?;
sqlx::query("DELETE FROM apps WHERE id = ?")
.bind(&id)
.execute(&pool)
.await?;
use serde::{Deserialize, Serialize};
use sqlx::FromRow;
use chrono::{DateTime, Utc};
use uuid::Uuid;
#[derive(Debug, Clone, Serialize, Deserialize, FromRow)]
pub struct App {
pub id: String,
pub name: String,
pub git_url: String,
pub branch: String,
pub port: i64,
pub domain: Option<String>,
pub healthcheck: Option<String>,
pub cpu_limit: Option<String>,
pub memory_limit: Option<String>,
pub environment: Option<String>,
pub project_id: Option<String>,
pub created_at: DateTime<Utc>,
pub updated_at: DateTime<Utc>,
}
impl App {
pub async fn get_by_id(pool: &SqlitePool, id: &str) -> Result<Option<Self>> {
sqlx::query_as("SELECT * FROM apps WHERE id = ?")
.bind(id)
.fetch_optional(pool)
.await
.map_err(Into::into)
}
}
Migrations live in migrations/ directory:
migrations/
├── 001_initial.sql
├── 002_add_webhooks.sql
├── 003_add_env_vars.sql
...
// At startup in main.rs
sqlx::migrate!("./migrations")
.run(&pool)
.await?;
sqlite3 data/rivetr.db "SELECT * FROM _sqlx_migrations"
CREATE TABLE apps (
id TEXT PRIMARY KEY,
name TEXT NOT NULL UNIQUE,
git_url TEXT NOT NULL,
branch TEXT NOT NULL DEFAULT 'main',
port INTEGER NOT NULL DEFAULT 3000,
domain TEXT,
healthcheck TEXT,
cpu_limit TEXT,
memory_limit TEXT,
environment TEXT DEFAULT 'development',
project_id TEXT REFERENCES projects(id),
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE deployments (
id TEXT PRIMARY KEY,
app_id TEXT NOT NULL REFERENCES apps(id),
commit_sha TEXT,
status TEXT NOT NULL DEFAULT 'pending',
container_id TEXT,
image_tag TEXT,
error_message TEXT,
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
finished_at DATETIME
);
CREATE TABLE env_vars (
id TEXT PRIMARY KEY,
app_id TEXT NOT NULL REFERENCES apps(id),
key TEXT NOT NULL,
value TEXT NOT NULL, -- Encrypted with AES-256-GCM
is_secret BOOLEAN DEFAULT 0,
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
UNIQUE(app_id, key)
);
CREATE TABLE deployment_logs (
id TEXT PRIMARY KEY,
deployment_id TEXT NOT NULL REFERENCES deployments(id),
level TEXT NOT NULL DEFAULT 'info',
message TEXT NOT NULL,
timestamp DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
);
# Open SQLite CLI
sqlite3 data/rivetr.db
# List all tables
.tables
# Show table schema
.schema apps
# Check WAL mode
PRAGMA journal_mode;
# Check foreign keys
PRAGMA foreign_keys;
# Recent deployments
SELECT id, app_id, status, created_at FROM deployments ORDER BY created_at DESC LIMIT 10;
# Failed deployments with errors
SELECT id, app_id, error_message, created_at FROM deployments WHERE status = 'failed' ORDER BY created_at DESC;
# Apps with their deployment counts
SELECT a.name, COUNT(d.id) as deploys FROM apps a LEFT JOIN deployments d ON a.id = d.app_id GROUP BY a.id;
PRAGMA journal_mode; should return "wal"SELECT * FROM _sqlx_migrationsrivetr.db for fresh start (dev only)ON DELETE CASCADE or delete children firsti64 not i32