Implements Turso edge SQLite database with libSQL client, embedded replicas, and vector search. Use when building edge-first apps, implementing embedded databases, or needing SQLite with global replication.
Adds Turso edge SQLite database support with libSQL client, embedded replicas, and vector search. Use when building edge-first apps, implementing embedded databases, or needing SQLite with global replication.
/plugin marketplace add mgd34msu/goodvibes-plugin/plugin install goodvibes@goodvibes-marketThis skill inherits all available tools. When active, it can use any tool Claude has access to.
references/embedded-replicas.mdreferences/vector-search.mdTurso is an edge-hosted SQLite database built on libSQL. It provides global replication, embedded replicas for ultra-low latency, and native vector search.
# Install CLI
brew install tursodatabase/tap/turso
# Authenticate
turso auth login
# Create database
turso db create my-app
# Get connection URL
turso db show my-app --url
# Create auth token
turso db tokens create my-app
npm install @libsql/client
import { createClient } from '@libsql/client'
const client = createClient({
url: process.env.TURSO_DATABASE_URL!,
authToken: process.env.TURSO_AUTH_TOKEN!
})
// Execute query
const result = await client.execute('SELECT * FROM users')
console.log(result.rows)
await client.execute(`
CREATE TABLE IF NOT EXISTS users (
id INTEGER PRIMARY KEY AUTOINCREMENT,
email TEXT UNIQUE NOT NULL,
name TEXT,
created_at TEXT DEFAULT CURRENT_TIMESTAMP
)
`)
// Single insert with parameters
const result = await client.execute({
sql: 'INSERT INTO users (email, name) VALUES (?, ?)',
args: ['user@example.com', 'John Doe']
})
console.log('Inserted ID:', result.lastInsertRowid)
// Named parameters
await client.execute({
sql: 'INSERT INTO users (email, name) VALUES (:email, :name)',
args: { email: 'alice@example.com', name: 'Alice' }
})
// All rows
const { rows } = await client.execute('SELECT * FROM users')
// With parameters
const { rows } = await client.execute({
sql: 'SELECT * FROM users WHERE id = ?',
args: [userId]
})
// Single row
const user = rows[0]
const result = await client.execute({
sql: 'UPDATE users SET name = ? WHERE id = ?',
args: ['Updated Name', userId]
})
console.log('Rows affected:', result.rowsAffected)
await client.execute({
sql: 'DELETE FROM users WHERE id = ?',
args: [userId]
})
Execute multiple statements in a single round-trip:
const results = await client.batch([
{
sql: 'INSERT INTO users (email, name) VALUES (?, ?)',
args: ['user1@example.com', 'User 1']
},
{
sql: 'INSERT INTO users (email, name) VALUES (?, ?)',
args: ['user2@example.com', 'User 2']
},
'SELECT * FROM users'
], 'write')
// Last result contains SELECT output
const users = results[2].rows
const transaction = await client.transaction('write')
try {
await transaction.execute({
sql: 'INSERT INTO accounts (user_id, balance) VALUES (?, ?)',
args: [userId, 1000]
})
await transaction.execute({
sql: 'UPDATE users SET has_account = 1 WHERE id = ?',
args: [userId]
})
await transaction.commit()
} catch (error) {
await transaction.rollback()
throw error
}
Embedded replicas provide local read access with automatic sync from the primary database.
import { createClient } from '@libsql/client'
const client = createClient({
url: 'file:local-replica.db', // Local file
syncUrl: process.env.TURSO_DATABASE_URL!,
authToken: process.env.TURSO_AUTH_TOKEN!,
syncInterval: 60 // Sync every 60 seconds
})
// Manual sync
await client.sync()
// Write to remote, sync, then read locally
await client.execute({
sql: 'INSERT INTO posts (title) VALUES (?)',
args: ['New Post']
})
await client.sync()
// Now read from local replica
const { rows } = await client.execute('SELECT * FROM posts')
// wrangler.toml
// [vars]
// TURSO_DATABASE_URL = "libsql://..."
// TURSO_AUTH_TOKEN = "..."
import { createClient } from '@libsql/client/web'
export default {
async fetch(request: Request, env: Env) {
const client = createClient({
url: env.TURSO_DATABASE_URL,
authToken: env.TURSO_AUTH_TOKEN
})
const { rows } = await client.execute('SELECT * FROM users')
return Response.json(rows)
}
}
// Use HTTP client for edge runtime
import { createClient } from '@libsql/client/web'
export const runtime = 'edge'
const client = createClient({
url: process.env.TURSO_DATABASE_URL!,
authToken: process.env.TURSO_AUTH_TOKEN!
})
export async function GET() {
const { rows } = await client.execute('SELECT * FROM users')
return Response.json(rows)
}
Turso has native vector support for AI applications:
// Create table with vector column
await client.execute(`
CREATE TABLE IF NOT EXISTS documents (
id INTEGER PRIMARY KEY,
content TEXT,
embedding F32_BLOB(1536) -- OpenAI embedding dimension
)
`)
// Insert with embedding
const embedding = await getEmbedding('Hello world') // Your embedding function
await client.execute({
sql: 'INSERT INTO documents (content, embedding) VALUES (?, vector(?))',
args: ['Hello world', JSON.stringify(embedding)]
})
// Similarity search
const queryEmbedding = await getEmbedding('greeting')
const { rows } = await client.execute({
sql: `
SELECT id, content,
vector_distance_cos(embedding, vector(?)) as distance
FROM documents
ORDER BY distance
LIMIT 10
`,
args: [JSON.stringify(queryEmbedding)]
})
npm install drizzle-orm
npm install -D drizzle-kit
// src/db/schema.ts
import { sqliteTable, text, integer } from 'drizzle-orm/sqlite-core'
export const users = sqliteTable('users', {
id: integer('id').primaryKey({ autoIncrement: true }),
email: text('email').notNull().unique(),
name: text('name'),
createdAt: text('created_at').default('CURRENT_TIMESTAMP')
})
export const posts = sqliteTable('posts', {
id: integer('id').primaryKey({ autoIncrement: true }),
title: text('title').notNull(),
content: text('content'),
authorId: integer('author_id').references(() => users.id)
})
// src/db/index.ts
import { drizzle } from 'drizzle-orm/libsql'
import { createClient } from '@libsql/client'
import * as schema from './schema'
const client = createClient({
url: process.env.TURSO_DATABASE_URL!,
authToken: process.env.TURSO_AUTH_TOKEN!
})
export const db = drizzle(client, { schema })
import { db } from './db'
import { users, posts } from './db/schema'
import { eq } from 'drizzle-orm'
// Insert
const newUser = await db.insert(users).values({
email: 'user@example.com',
name: 'John'
}).returning()
// Select with relations
const usersWithPosts = await db.query.users.findMany({
with: { posts: true }
})
// Update
await db.update(users)
.set({ name: 'Updated' })
.where(eq(users.id, 1))
// Delete
await db.delete(users).where(eq(users.id, 1))
npm install prisma @prisma/client @prisma/adapter-libsql @libsql/client
// prisma/schema.prisma
generator client {
provider = "prisma-client-js"
previewFeatures = ["driverAdapters"]
}
datasource db {
provider = "sqlite"
url = "file:./dev.db"
}
model User {
id Int @id @default(autoincrement())
email String @unique
name String?
posts Post[]
}
model Post {
id Int @id @default(autoincrement())
title String
author User @relation(fields: [authorId], references: [id])
authorId Int
}
import { PrismaClient } from '@prisma/client'
import { PrismaLibSQL } from '@prisma/adapter-libsql'
import { createClient } from '@libsql/client'
const libsql = createClient({
url: process.env.TURSO_DATABASE_URL!,
authToken: process.env.TURSO_AUTH_TOKEN!
})
const adapter = new PrismaLibSQL(libsql)
const prisma = new PrismaClient({ adapter })
// Use normally
const users = await prisma.user.findMany()
# List available locations
turso db locations
# Add replica in specific region
turso db replicate my-app fra # Frankfurt
turso db replicate my-app syd # Sydney
# List replicas
turso db show my-app
Turso automatically routes reads to the closest replica. The primary handles writes and propagates changes.
# Database operations
turso db create <name> [--location <loc>]
turso db destroy <name>
turso db list
turso db show <name>
# Replicas
turso db replicate <name> <location>
turso db unreplicate <name> <location>
turso db locations
# Tokens
turso db tokens create <name> [--expiration <duration>]
turso db tokens revoke <name> <token>
# Shell access
turso db shell <name>
# Groups (for multi-db)
turso group create <name>
turso db create <name> --group <group>
# .env
TURSO_DATABASE_URL="libsql://your-db-your-org.turso.io"
TURSO_AUTH_TOKEN="your-auth-token"
# For embedded replicas
TURSO_SYNC_URL="libsql://your-db-your-org.turso.io"
TURSO_LOCAL_DB="file:local.db"
This skill should be used when the user asks to "create an agent", "add an agent", "write a subagent", "agent frontmatter", "when to use description", "agent examples", "agent tools", "agent colors", "autonomous agent", or needs guidance on agent structure, system prompts, triggering conditions, or agent development best practices for Claude Code plugins.
This skill should be used when the user asks to "create a slash command", "add a command", "write a custom command", "define command arguments", "use command frontmatter", "organize commands", "create command with file references", "interactive command", "use AskUserQuestion in command", or needs guidance on slash command structure, YAML frontmatter fields, dynamic arguments, bash execution in commands, user interaction patterns, or command development best practices for Claude Code.
This skill should be used when the user asks to "create a hook", "add a PreToolUse/PostToolUse/Stop hook", "validate tool use", "implement prompt-based hooks", "use ${CLAUDE_PLUGIN_ROOT}", "set up event-driven automation", "block dangerous commands", or mentions hook events (PreToolUse, PostToolUse, Stop, SubagentStop, SessionStart, SessionEnd, UserPromptSubmit, PreCompact, Notification). Provides comprehensive guidance for creating and implementing Claude Code plugin hooks with focus on advanced prompt-based hooks API.