Token导航 LogoToken导航TokenDH.com
研究检索需要联网github未标认证来源可访问clear审计通过

axiom-sqlitedata-ref公理 sqlitedata 参考

Agent Skill

用于辅助数据库表结构、查询语句、迁移脚本和数据维护任务。它适合让 Agent 分析 schema、编写 SQL、排查查询问题、整理索引或生成迁移建议。使用时需要明确数据库类型、连接环境和目标表,区分只读分析与写入变更;涉及删除、更新、迁移和批量导入时,应优先 dry-run、备份或事务保护,避免误操作。

总安装

4,529

周安装

185

GitHub Stars

873

下载量

1,450
CodexClaudeCursorGemini CLI

安装说明

本站只整理中文说明和来源信息,不托管安装包,也不代用户安装。

GitHub

来源数

3

许可证

MIT

最后核验

2026-05-01

来源状态

来源可访问

安装方式

通过对话安装

复制提示词发给支持本地命令或 Skills 的 AI 助手,先确认命令和权限,再让它执行。

请帮我安装这个 Agent Skill:axiom-sqlitedata-ref(公理 sqlitedata 参考)
来源仓库:https://github.com/charleswiltgen/axiom
仓库路径:skills/axiom-sqlitedata-ref
安装命令:
npx skills add https://github.com/charleswiltgen/axiom --skill axiom-sqlitedata-ref
安装前请先检查当前环境是否支持对应 CLI,并向我确认将要执行的命令、安装目录、联网范围和文件读写权限;确认后再执行。

命令行安装

复制命令到本机终端执行。不同来源提供的安装方式可能略有差异;本站展示可直接复制的安装命令,安装前请核对来源页面。

skills.shnpx skills
npx skills add https://github.com/charleswiltgen/axiom --skill axiom-sqlitedata-ref

简介

提供 SQLiteData 高级查询模式和架构组合技术参考。

  • 适用于 CTE、视图定义、自定义聚合和单表继承等复杂场景。
  • 基于 GRDB 和 StructuredQueries 构建,支持 Swift 6 并发。
  • 安装前建议确认权限范围和维护状态,避免触发联网或文件读写操作。
  • axiom-sqlitedata-ref 属于研究检索类 Skill,可作为该场景下的辅助能力补充。

SKILL.md

SQLiteData Advanced Reference

Overview

Advanced query patterns and schema composition techniques for SQLiteData by Point-Free. Built on GRDB and StructuredQueries.

For core patterns (CRUD, CloudKit setup, @Table basics), see the axiom-sqlitedata discipline skill.

This reference covers advanced querying, schema composition, views, and custom aggregates.

Requires iOS 17+, Swift 6 strict concurrency Framework SQLiteData 1.4+


Column Groups and Schema Composition

SQLiteData provides powerful tools for composing schema types, enabling reuse, better organization, and single-table inheritance patterns.

Column Groups

Group related columns into reusable types with @Selection:

// Define a reusable column group
@Selection
struct Timestamps {
    let createdAt: Date
    let updatedAt: Date?
}

// Use in multiple tables
@Table
nonisolated struct RemindersList: Identifiable {
    let id: UUID
    var title = ""
    let timestamps: Timestamps  // Embedded column group
}

@Table
nonisolated struct Reminder: Identifiable {
    let id: UUID
    var title = ""
    var isCompleted = false
    let timestamps: Timestamps  // Same group, reused
}

Important: SQLite has no concept of grouped columns. Flatten all groupings in your CREATE TABLE:

CREATE TABLE "remindersLists" (
    "id" TEXT PRIMARY KEY NOT NULL DEFAULT (uuid()),
    "title" TEXT NOT NULL DEFAULT '',
    "createdAt" TEXT NOT NULL,
    "updatedAt" TEXT
) STRICT

Querying Column Groups

Access fields inside groups with dot syntax:

// Query a field inside the group
RemindersList
    .where { $0.timestamps.createdAt <= cutoffDate }
    .fetchAll(db)

// Compare entire group (flattens to tuple in SQL)
RemindersList
    .where {
        $0.timestamps <= Timestamps(createdAt: date1, updatedAt: date2)
    }

Nesting Groups in @Selection

Use column groups in custom query results:

@Selection
struct Row {
    let reminderTitle: String
    let listTitle: String
    let timestamps: Timestamps  // Nested group
}

let results = try Reminder
    .join(RemindersList.all) { $0.remindersListID.eq($1.id) }
    .select {
        Row.Columns(
            reminderTitle: $0.title,
            listTitle: $1.title,
            timestamps: $0.timestamps  // Pass entire group
        )
    }
    .fetchAll(db)

Single-Table Inheritance with Enums

Model polymorphic data using @CasePathable @Selection enums — a value-type alternative to class inheritance:

import CasePaths

@Table
nonisolated struct Attachment: Identifiable {
    let id: UUID
    let kind: Kind

    @CasePathable @Selection
    enum Kind {
        case link(URL)
        case note(String)
        case image(URL)
    }
}

Note: @CasePathable is required and comes from Point-Free's CasePaths library.

SQL Schema for Enum Tables

Flatten all cases into nullable columns:

CREATE TABLE "attachments" (
    "id" TEXT PRIMARY KEY NOT NULL DEFAULT (uuid()),
    "link" TEXT,
    "note" TEXT,
    "image" TEXT
) STRICT

Querying Enum Tables

// Fetch all — decoding determines which case
let attachments = try Attachment.all.fetchAll(db)

// Filter by case
let images = try Attachment
    .where { $0.kind.image.isNot(nil) }
    .fetchAll(db)

Inserting Enum Values

try Attachment.insert {
    Attachment.Draft(kind: .note("Hello world!"))
}
.execute(db)
// Inserts: (id, NULL, 'Hello world!', NULL)

Updating Enum Values

try Attachment.find(id).update {
    $0.kind = #bind(.link(URL(string: "https://example.com")!))
}
.execute(db)
// Sets link column, NULLs note and image columns

Complex Enum Cases with Grouped Columns

Enum cases can hold structured data using nested @Selection types:

@Table
nonisolated struct Attachment: Identifiable {
    let id: UUID
    let kind: Kind

    @CasePathable @Selection
    enum Kind {
        case link(URL)
        case note(String)
        case image(Attachment.Image)  // Fully qualify nested types
    }

    @Selection
    struct Image {
        var caption = ""
        var url: URL
    }
}

SQL schema flattens all nested fields:

CREATE TABLE "attachments" (
    "id" TEXT PRIMARY KEY NOT NULL DEFAULT (uuid()),
    "link" TEXT,
    "note" TEXT,
    "caption" TEXT,
    "url" TEXT
) STRICT

Passing Rows to Database Functions

With column groups, @DatabaseFunction can accept entire table rows:

@DatabaseFunction
func isPastDue(reminder: Reminder) -> Bool {
    !reminder.isCompleted && reminder.dueDate < Date()
}

// Use in queries — columns are flattened/reconstituted automatically
let pastDue = try Reminder
    .where { $isPastDue(reminder: $0) }
    .fetchAll(db)

Column Groups vs SwiftData Inheritance

ApproachSQLiteDataSwiftData
TypeValue types (enums/structs)Reference types (classes)
ExhaustivityCompiler-enforced switchRuntime type checking
VerbosityConcise enum casesVerbose class hierarchy
InheritanceSingle-table via enum@Model class inheritance
Reusable columns@Selection groupsManual repetition

SwiftData equivalent (more verbose):

@Model class Attachment { var isActive: Bool }
@Model class Link: Attachment { var url: URL }
@Model class Note: Attachment { var note: String }
@Model class Image: Attachment { var url: URL }
// Each needs explicit init calling super.init

Query Composition

Build reusable scopes as static properties/methods:

extension Item {
    static let active = Item.where { !$0.isArchived && !$0.isDeleted }
    static let inStock = Item.where(\.isInStock)

    static func createdAfter(_ date: Date) -> Where<Item> {
        Item.where { $0.createdAt > date }
    }
}

// Chain scopes
let results = try Item.active.inStock.order(by: \.title).fetchAll(db)

// Use as base for @FetchAll
@FetchAll(Item.active) var items

Extend Where<Item> to add composable filters:

extension Where<Item> {
    func matching(_ search: String) -> Where<Item> {
        self.where { $0.title.contains(search) || $0.notes.contains(search) }
    }
}
let results = try Item.inStock.matching(searchText).fetchAll(db)

Custom Fetch Requests with @Fetch

Use @Fetch when you need multiple pieces of data in a single read transaction (use @FetchAll/@FetchOne for single-table queries):

struct DashboardRequest: FetchKeyRequest {
    struct Value: Sendable {
        let totalItems: Int
        let activeItems: [Item]
        let categories: [Category]
    }

    func fetch(_ db: Database) throws -> Value {
        try Value(
            totalItems: Item.count().fetchOne(db) ?? 0,
            activeItems: Item.where { !$0.isArchived }.order(by: \.updatedAt.desc()).limit(10).fetchAll(db),
            categories: Category.order(by: \.name).fetchAll(db)
        )
    }
}

@Fetch(DashboardRequest()) var dashboard

Dynamic loading with .load():

@Fetch var results = SearchRequest.Value()

.task(id: query) {
    try? await $results.load(SearchRequest(query: query), animation: .default)
}

Key benefits: atomic reads, automatic observation, type-safe results.


Advanced Query Patterns

String Functions

FunctionUsageSQL
upper() / lower()$0.title.upper()UPPER/LOWER
trim() / ltrim() / rtrim()$0.title.trim()TRIM
substr(start, len)$0.title.substr(0, 3)SUBSTR
replace(old, new)$0.title.replace("old", "new")REPLACE
length()$0.title.length()LENGTH
instr(search)$0.title.instr("search") > 0INSTR
like(pattern)$0.title.like("%phone%")LIKE
hasPrefix / hasSuffix / contains$0.title.contains("Max")Swift-style
collate(.nocase)$0.title.collate(.nocase).eq(#bind("X"))COLLATE

Null Handling

// Coalesce — first non-null value
let name = try User.select { $0.nickname ?? $0.firstName ?? "Anonymous" }.fetchAll(db)

// Null checks
let withDue = try Reminder.where { $0.dueDate.isNot(nil) }.fetchAll(db)
let noDue = try Reminder.where { $0.dueDate.is(nil) }.fetchAll(db)

// Null-safe ordering
let sorted = try Item.order { $0.priority.desc(nulls: .last) }.fetchAll(db)

Range and Set Membership

// IN (set or subquery)
let selected = try Item.where { $0.id.in(selectedIds) }.fetchAll(db)
let inActive = try Item.where { $0.categoryID.in(
    Category.where(\.isActive).select(\.id)
)}.fetchAll(db)

// NOT IN
let excluded = try Item.where { !$0.id.in(excludedIds) }.fetchAll(db)

// BETWEEN (or Swift range syntax)
let midRange = try Item.where { $0.price.between(10, and: 100) }.fetchAll(db)

Pagination

// Offset-based
let items = try Item.order(by: \.createdAt).limit(20, offset: page * 20).fetchAll(db)

// Cursor-based (more efficient for deep pages)
let items = try Item.where { $0.id > lastSeenId }.order(by: \.id).limit(20).fetchAll(db)

Distinct Results

let categories = try Item.select(\.category).distinct().fetchAll(db)

RETURNING Clause

Fetch generated values from INSERT, UPDATE, or DELETE operations:

// Insert and get auto-generated ID
let newId = try Item.insert { Item.Draft(title: "New Item") }
    .returning(\.id).fetchOne(db)

// Update and return new values
let updates = try Item.find(id).update { $0.count += 1 }
    .returning { ($0.id, $0.count) }.fetchOne(db)

// Capture deleted records before removal
let deleted = try Item.where { $0.isArchived }.delete()
    .returning(Item.self).fetchAll(db)

Use RETURNING to avoid a second query for auto-generated IDs, audit deletions, or verify updates.


Joins

Join Types

// INNER JOIN — only matching rows
let items = try Item.join(Category.all) { $0.categoryID.eq($1.id) }.fetchAll(db)

// LEFT JOIN — all from left, matching from right (nullable)
let items = try Item.leftJoin(Category.all) { $0.categoryID.eq($1.id) }
    .select { ($0, $1) }  // (Item, Category?)
    .fetchAll(db)

Also available: .rightJoin() (all from right) and .fullJoin() (all from both).

Multi-table joins chain naturally:

extension Reminder {
    static let withTags = group(by: \.id)
        .leftJoin(ReminderTag.all) { $0.id.eq($1.reminderID) }
        .leftJoin(Tag.all) { $1.tagID.eq($2.primaryKey) }
}

Self-Joins with TableAlias

struct ManagerAlias: TableAlias { typealias Table = Employee }

let employeesWithManagers = try Employee
    .leftJoin(Employee.all.as(ManagerAlias.self)) { $0.managerID.eq($1.id) }
    .select { (employeeName: $0.name, managerName: $1.name) }
    .fetchAll(db)

Case Expressions

// Simple case — map values
let labels = try Item.select {
    Case($0.priority).when(1, then: "Low").when(2, then: "Medium")
        .when(3, then: "High").else("Unknown")
}.fetchAll(db)

// Searched case — boolean conditions
let status = try Order.select {
    Case().when($0.shippedAt.isNot(nil), then: "Shipped")
        .when($0.paidAt.isNot(nil), then: "Paid").else("Unknown")
}.fetchAll(db)

// Case in updates (toggle pattern)
try Reminder.find(id).update {
    $0.status = Case($0.status)
        .when(#bind(.incomplete), then: #bind(.completing))
        .when(#bind(.completing), then: #bind(.completed))
        .else(#bind(.incomplete))
}.execute(db)

Common Table Expressions (CTEs)

Non-Recursive CTEs

// Single CTE
let expensiveItems = try With {
    Item.where { $0.price > 1000 }
} query: { expensive in
    expensive.order(by: \.price).limit(10)
}.fetchAll(db)

// Multiple CTEs
let report = try With {
    Customer.where { $0.totalSpent > 10000 }
} with: {
    Order.where { $0.createdAt > lastMonth }
} query: { highValue, recentOrders in
    highValue.join(recentOrders) { $0.id.eq($1.customerID) }
        .select { ($0.name, $1.total) }
}.fetchAll(db)

Use CTEs to break complex queries into readable parts, reuse subqueries, or improve query plans.

Recursive CTEs

Query hierarchical data (trees, org charts, threaded comments):

@Table
nonisolated struct Category: Identifiable {
    let id: UUID
    var name = ""
    var parentID: UUID?  // Self-referential
}

// Get all descendants of a root category
let allDescendants = try With {
    Category.where { $0.id.eq(#bind(rootCategoryId)) }  // Base case
} recursiveUnion: { cte in
    Category.all.join(cte) { $0.parentID.eq($1.id) }.select { $0 }  // Recursive case
} query: { cte in
    cte.order(by: \.name)
}.fetchAll(db)

Reverse the join condition ($0.id.eq($1.parentID)) to walk up the tree instead of down.


Full-Text Search (FTS5)

Basic FTS5

@Table
struct ReminderText: FTS5 {
    let rowid: Int
    let title: String
    let notes: String
    let tags: String
}

// Create FTS table in migration
try #sql(
    """
    CREATE VIRTUAL TABLE "reminderTexts" USING fts5(
        "title", "notes", "tags",
        tokenize = 'trigram'
    )
    """
)
.execute(db)

Advanced FTS5 Features

// Highlight search terms
let results = try ItemText.where { $0.match(query) }
    .select { ($0.rowid, $0.title.highlight("<b>", "</b>")) }.fetchAll(db)

// Snippets with context
let snippets = try ItemText.where { $0.match(query) }
    .select { $0.description.snippet("<b>", "</b>", "...", 64) }.fetchAll(db)

// BM25 relevance ranking
let ranked = try ItemText.where { $0.match(query) }
    .order { $0.bm25().desc() }.fetchAll(db)

Aggregation

String and JSON Aggregation

// groupConcat — comma-separated tags per item
let itemsWithTags = try Item.group(by: \.id)
    .leftJoin(ItemTag.all) { $0.id.eq($1.itemID) }
    .leftJoin(Tag.all) { $1.tagID.eq($2.id) }
    .select { ($0.title, $2.name.groupConcat(separator: ", ")) }
    .fetchAll(db)
// ("iPhone", "electronics, mobile, apple")

// jsonGroupArray — aggregate into JSON array
let itemsJson = try Store.group(by: \.id)
    .leftJoin(Item.all) { $0.id.eq($1.storeID) }
    .select { ($0.name, $1.title.jsonGroupArray()) }
    .fetchAll(db)

Options: .groupConcat(distinct: true), .groupConcat(order: {$0.asc()}), .jsonGroupArray(filter: $1.isActive), jsonObject("key", $0.value).

Conditional Aggregation

All aggregate functions accept a filter: parameter:

let stats = try Item.select {
    Stats.Columns(
        total: $0.count(),
        activeCount: $0.count(filter: $0.isActive),
        avgActivePrice: $0.price.avg(filter: $0.isActive),
        totalRevenue: $0.revenue.sum(filter: $0.status.eq(#bind(.completed)))
    )
}.fetchOne(db)

HAVING Clause

.where() filters rows before grouping; .having() filters groups after aggregation:

let frequentCustomers = try Customer.group(by: \.id)
    .leftJoin(Order.all) { $0.id.eq($1.customerID) }
    .having { $1.count() > 5 }
    .select { ($0.name, $1.count()) }
    .fetchAll(db)

Schema Creation with #sql Macro

The #sql macro enables type-safe raw SQL for schema creation and migrations.

CREATE TABLE

migrator.registerMigration("Create initial tables") { db in
    try #sql("""
        CREATE TABLE "items" (
            "id" TEXT PRIMARY KEY NOT NULL DEFAULT (uuid()),
            "title" TEXT NOT NULL DEFAULT '',
            "isInStock" INTEGER NOT NULL DEFAULT 1,
            "price" REAL NOT NULL DEFAULT 0.0,
            "createdAt" TEXT NOT NULL DEFAULT (datetime('now'))
        ) STRICT
        """).execute(db)
}

Parameter Interpolation

  • \(value) → Automatically escaped (safe for user input)
  • \(raw: value) → Inserted literally (only for identifiers you control)
  • Never use \(raw: userInput) — SQL injection vulnerability

Other DDL

// CREATE INDEX (with optional WHERE for partial indexes)
try #sql("""CREATE INDEX "idx_items_search" ON "items" ("title") WHERE "isArchived" = 0""").execute(db)

// CREATE TRIGGER
try #sql("""
    CREATE TRIGGER "update_timestamp" AFTER UPDATE ON "items"
    BEGIN UPDATE "items" SET "updatedAt" = datetime('now') WHERE "id" = NEW."id"; END
    """).execute(db)

// ALTER TABLE
try #sql("""ALTER TABLE "items" ADD COLUMN "notes" TEXT NOT NULL DEFAULT ''""").execute(db)

Use #sql for DDL (CREATE, ALTER, indexes, triggers). Use the query builder for regular CRUD.

Foreign Key Relationships

migrator.registerMigration("Create tables with foreign keys") { db in
    try #sql("""
        CREATE TABLE "itemCategories" (
            "itemID" TEXT NOT NULL REFERENCES "items"("id") ON DELETE CASCADE,
            "categoryID" TEXT NOT NULL REFERENCES "categories"("id") ON DELETE CASCADE,
            PRIMARY KEY ("itemID", "categoryID")
        ) STRICT
        """).execute(db)
}

Critical: Enable foreign key enforcement — SQLite disables it by default:

var configuration = Configuration()
configuration.prepareDatabase { db in
    try db.execute(sql: "PRAGMA foreign_keys = ON")
}

Without PRAGMA foreign_keys = ON, REFERENCES and ON DELETE CASCADE are silently ignored.

Transaction Context for Batch Operations

Wrap batch operations in explicit transactions for atomicity and performance:

try database.write { db in
    // All operations share one transaction
    for item in items {
        try Item.insert { Item.Draft(title: item.title) }.execute(db)
    }
}
// Commits once on success, rolls back entirely on failure

The database.write {} block is already a transaction. For read-heavy batch analysis, use database.read {} which provides a consistent snapshot.


Database Views

@Selection for Custom Query Results

@Selection generates a .Columns type for compile-time verified query results:

@Selection
struct ReminderWithList: Identifiable {
    var id: Reminder.ID { reminder.id }
    let reminder: Reminder
    let remindersList: RemindersList
}

@FetchAll(
    Reminder.join(RemindersList.all) { $0.remindersListID.eq($1.id) }
        .select { ReminderWithList.Columns(reminder: $0, remindersList: $1) }
)
var reminders: [ReminderWithList]

Also works for aggregate queries — see the Conditional Aggregation section above.

Temporary Views

For reusable complex queries, combine @Table @Selection and createTemporaryView:

@Table @Selection
private struct ReminderWithList {
    let reminderTitle: String
    let remindersListTitle: String
}

try database.write { db in
    try ReminderWithList.createTemporaryView(
        as: Reminder.join(RemindersList.all) { $0.remindersListID.eq($1.id) }
            .select { ReminderWithList.Columns(reminderTitle: $0.title, remindersListTitle: $1.title) }
    ).execute(db)
}

// Query like a table — join complexity hidden
let results = try ReminderWithList.order { ($0.remindersListTitle, $0.reminderTitle) }.fetchAll(db)

Temporary views exist for the connection lifetime. For persistent views, use #sql("CREATE VIEW...") in migrations.

To make views writable, add createTemporaryTrigger(insteadOf:.insert {...}) to reroute operations to underlying tables.


Custom Aggregate Functions

Write complex aggregation in Swift with @DatabaseFunction, avoiding contorted SQL subqueries:

// 1. Define — takes Sequence<T?>, returns aggregate result
@DatabaseFunction
func mode(priority priorities: some Sequence<Reminder.Priority?>) -> Reminder.Priority? {
    var occurrences: [Reminder.Priority: Int] = [:]
    for priority in priorities {
        guard let priority else { continue }
        occurrences[priority, default: 0] += 1
    }
    return occurrences.max { $0.value < $1.value }?.key
}

// 2. Register
configuration.prepareDatabase { db in db.add(function: $mode) }

// 3. Use in queries
let results = try RemindersList.group(by: \.id)
    .leftJoin(Reminder.all) { $0.id.eq($1.remindersListID) }
    .select { ($0.title, $mode(priority: $1.priority)) }
    .fetchAll(db)

Common uses: mode, median, weighted average, custom filtering. Functions run in Swift (not SQLite's C engine), so use built-in aggregates (count, sum, avg, min, max) when possible.


Batch Upsert Performance

For high-volume sync (50K+ records), use cached statements instead of the type-safe API:

func batchUpsert(_ items: [Item], in db: Database) throws {
    let statement = try db.cachedStatement(sql: """
        INSERT INTO items (id, name, libraryID, remoteID, updatedAt)
        VALUES (?, ?, ?, ?, ?)
        ON CONFLICT(libraryID, remoteID) DO UPDATE SET
            name = excluded.name, updatedAt = excluded.updatedAt
        WHERE excluded.updatedAt >= items.updatedAt
        """)
    for item in items {
        try statement.execute(arguments: [item.id, item.name, item.libraryID, item.remoteID, item.updatedAt])
    }
}

For even higher throughput, build multi-row VALUES clauses. Query the variable limit at runtime: sqlite3_limit(db.sqliteConnection, SQLITE_LIMIT_VARIABLE_NUMBER, -1) (32,766 on iOS 14+, 999 on iOS 13).

PatternThroughputTrade-off
Type-safe upsert~1K rows/secBest DX, compile-time checks
Cached statement~10K rows/secGood balance
Multi-row VALUES~50K rows/secMost complex

Miscellaneous Advanced Patterns

Database Triggers

try database.write { db in
    try Reminder.createTemporaryTrigger(
        after: .insert { new in
            Reminder
                .find(new.id)
                .update {
                    $0.position = Reminder.select { ($0.position.max() ?? -1) + 1 }
                }
        }
    )
    .execute(db)
}

Custom Update Logic

extension Updates<Reminder> {
    mutating func toggleStatus() {
        self.status = Case(self.status)
            .when(#bind(.incomplete), then: #bind(.completing))
            .else(#bind(.incomplete))
    }
}

// Usage
try Reminder.find(reminder.id).update { $0.toggleStatus() }.execute(db)

Enum Support

enum Priority: Int, QueryBindable {
    case low = 1
    case medium = 2
    case high = 3
}

enum Status: Int, QueryBindable {
    case incomplete = 0
    case completing = 1
    case completed = 2
}

@Table
nonisolated struct Reminder: Identifiable {
    let id: UUID
    var priority: Priority?
    var status: Status = .incomplete
}

Compound Selects

// UNION (deduplicated), UNION ALL (keep duplicates)
let all = try Customer.select(\.email).union(Supplier.select(\.email)).fetchAll(db)

// INTERSECT (in both), EXCEPT (in first but not second)
let shared = try Customer.select(\.email).intersect(Supplier.select(\.email)).fetchAll(db)

Resources

GitHub: pointfreeco/sqlite-data, pointfreeco/swift-structured-queries, groue/GRDB.swift

Skills: axiom-sqlitedata, axiom-sqlitedata-migration, axiom-database-migration, axiom-grdb


Targets: iOS 17+, Swift 6 Framework: SQLiteData 1.4+ History: See git log for changes

适合场景

01

用户想查找某类 Agent Skill 时

02

需要根据任务场景推荐可安装能力包时

03

需要对比不同来源的安装命令和来源信息时

04

需要参考平台分布和安装热度时

能力概览

能力 1

按任务关键词查找相关 Skills

能力 2

展示可复制的安装命令

能力 3

保留来源站点、仓库和原始说明,方便继续核验

能力 4

补充不同宿主或平台的使用分布数据

能力 5

展示第三方安全扫描或审计结果

安装后应在对应宿主中按原始 README 的触发条件使用;具体调用方式请以来源页面和 README 为准。

平台分布

Claude Code

31.5%
按下载量换算457

OpenCode

24.27%
按下载量换算352

Codex

16.22%
按下载量换算235

Cursor

11.9%
按下载量换算173

windsurf

8.45%
按下载量换算123

Antigravity

3.24%
按下载量换算47

安全审计

Gen Agent Trust Hub

通过

Socket

通过

Snyk

通过

权限和风险

需要联网

该 Skill 可能需要联网访问来源站点、仓库或外部 API;具体网络访问范围需要结合源码和 README 复核。

安装前确认

本站仅展示第三方公开信息,不托管安装包,不提供自动安装或运行环境。安装前应自行审查源码、依赖和命令行为。

来源信息

继续浏览同类 Skills