agentleFS
Fe2-O3Fe2-O3/swift-field-guide/swift-data/SKILL.md

swift-data

Skill0 starsChanged 2 months agoMITView on GitHub

Use for ANY Swift/iOS/macOS data persistence work: persisting data, models, or a database; Core Data (NSManagedObject, NSPersistentContainer, NSFetchedResultsController, stack setup, threading, migrations, NSPersistentCloudKitContainer/CloudKit sync); SwiftData (@Model, @Query, @Relationship, ModelContainer, predicates); SQLiteData (@Table, @FetchAll, @FetchOne, @Fetch macros, CloudKit private-database sync); GRDB (raw SQL, DatabaseQueue/DatabasePool, complex joins, window functions, ValueObservation). Also use when deciding WHICH persistence framework to use, migrating between them, or reviewing/writing/debugging persistence code in an existing project. Consolidates four prior skills (core-data-expert, swiftdata-pro, sqlite-data, grdb) into one — always load this first for persistence work rather than guessing at framework-specific APIs from memory.

The file

We split this skill into the rules it gives an agent

6 rules. About 0 are common, 5 are distinctive, and 1 is very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈5

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 1

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Very specific:

    Look at the project (imports, Package.swift/.xcodeproj dependencies, existing model files) before assuming.

    line 14
  2. Distinctive:

    If there's no existing code (greenfield decision), use this rule of thumb:

    line 23
  3. Distinctive:

    Don't load more than one framework's reference unless the task genuinely spans two (e.g., a SQLiteData app with one GRDB escape-hatch …

    line 40
  4. Distinctive:

    Determine the deployment target before proposing an API: All four gate features by OS version (Core Data staged migration iOS 17+, …

    line 47
  5. Distinctive:

    If CloudKit is involved, sync/schema implications were considered, not just the local-store change.

    line 57
  6. Distinctive:

    Read the framework-specific reference file rather than answering from general SQL/ORM knowledge.

    line 59

≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

Swift Data — persistence router

Four different Swift persistence frameworks solve overlapping problems in incompatible ways. Getting this wrong costs real time: Core Data's NSManagedObjectID rules don't apply to SwiftData, SwiftData's #Predicate macro doesn't support what GRDB's raw SQL does, and SQLiteData's macros aren't GRDB's query interface. Rather than guessing from general Swift/SQL knowledge, identify the framework first, then read the matching reference below — it has the framework's actual rules, crash patterns, and idioms in depth.

This skill is a router, not a rulebook. Each reference file below carries the full content of what used to be a separate skill (core-data-expert, swiftdata-pro, sqlite-data, grdb) — nothing was cut, only reorganized.

Step 1: identify the framework

Look at the project (imports, Package.swift/.xcodeproj dependencies, existing model files) before assuming. Signals:

See thisFramework
import CoreData, NSManagedObject, .xcdatamodeld, NSPersistentContainerCore Data
import SwiftData, @Model, @Query, ModelContainerSwiftData
import SQLiteData, @Table, @FetchAll, @FetchOne, @FetchSQLiteData
import GRDB, DatabaseQueue, DatabasePool, raw SQL strings, Record protocolsGRDB

If there's no existing code (greenfield decision), use this rule of thumb:

  • Default for new SwiftUI apps, iOS 17+: SwiftData — least boilerplate, native @Query/@Model.
  • Need CloudKit sync but want type-safe @Table macros over raw SQL: SQLiteData.
  • Need raw SQL, complex joins (4+ tables), window functions, or reactive ValueObservation, or are dropping down from SQLiteData for performance: GRDB.
  • Existing large Core Data codebase, or need NSFetchedResultsController-style diffable UIKit integration: stay on Core Data — don't migrate speculatively.
  • Have an existing app already committed to one of the four: stay on it unless the user explicitly asks about migrating. Migrating persistence layers is high-risk; don't suggest it unprompted.

Two frameworks coexist deliberately in some codebases: SQLiteData for most tables, GRDB for the handful of queries where SQLiteData's macros aren't expressive enough. See references/grdb.md → "When to Use GRDB vs SQLiteData" for the split.

Step 2: read the matching reference

  • Core Data → references/core-data/overview.md (start here — triage template, routing map, common-error lookup), then the specific file it points to (stack-setup.md, fetch-requests.md, threading.md, concurrency.md, batch-operations.md, persistent-history.md, model-configuration.md, migration.md, cloudkit-integration.md, performance.md, testing.md, project-audit.md, glossary.md). references/core-data/_index.md has a full problem→file lookup table.
  • SwiftData → references/swiftdata.md — review process, core instructions, output format, then sections on core rules, predicates, CloudKit, indexing (iOS 18+), and class inheritance (iOS 26+).
  • SQLiteData → references/sqlitedata.md — section guide up top routes to table models, query basics/advanced, writes, SwiftUI/UIKit view integration, migrations, CloudKit sync, dependency injection, testing, and advanced optimization.
  • GRDB → references/grdb.md — getting started, queries, ValueObservation, migrations, performance, plus the GRDB-vs-SQLiteData comparison table.

Don't load more than one framework's reference unless the task genuinely spans two (e.g., a SQLiteData app with one GRDB escape-hatch query, or a Core Data → SwiftData migration question).

Cross-cutting behavior contract

These apply regardless of which framework is in play — they're why, not just what, because the underlying reason (object lifetime, actor isolation, schema evolution) recurs across all four:

  1. Never let a model/record instance cross a concurrency boundary it doesn't own. Core Data: pass NSManagedObjectID, not NSManagedObject, across contexts. SwiftData: ModelContext and model instances must never cross actor boundaries — pass PersistentIdentifier and re-fetch. GRDB/SQLiteData: reads and writes go through the database connection/queue, not cached record instances shared across threads. The common failure mode is the same crash shape (concurrent access, stale reference) with a framework-specific fix.
  2. Determine the deployment target before proposing an API. All four gate features by OS version (Core Data staged migration iOS 17+, SwiftData indexing iOS 18+/class inheritance iOS 26+, etc.) — check before recommending, don't assume latest.
  3. Migrations are not optional busywork. A schema change without a matching migration is a runtime crash waiting to happen in every one of these frameworks, not just a style nit — treat "did you add a migration" as a required check on any model/table change.
  4. CloudKit constraints bind the schema, not just the code. Core Data's production CloudKit schema is immutable once shipped; SQLiteData's CloudKit sync needs full SyncDelegate implementation for production. Flag CloudKit involvement early — it changes what's safe to change later.
  5. Profile before optimizing. "Probably slow" isn't a diagnosis in any of these frameworks — use Instruments (Core Data), or EXPLAIN QUERY PLAN (GRDB/SQLiteData raw queries) before restructuring for performance.

Verification checklist (any framework, before calling persistence work done)

  • Confirmed which framework this project actually uses (didn't assume from the request wording).
  • Model/record instances aren't crossing threads or actors by reference.
  • Schema changes have a corresponding migration.
  • If CloudKit is involved, sync/schema implications were considered, not just the local-store change.
  • Performance claims are profiled, not guessed.
  • Read the framework-specific reference file rather than answering from general SQL/ORM knowledge.

Reference tree

references/
  core-data/            (Core Data — full former core-data-expert skill, 15 files)
    overview.md          entry point: triage template, routing map, common errors, verification
    _index.md             navigation index, problem→file lookup
    stack-setup.md, saving.md, fetch-requests.md, threading.md, concurrency.md,
    batch-operations.md, persistent-history.md, model-configuration.md, migration.md,
    cloudkit-integration.md, performance.md, testing.md, project-audit.md, glossary.md
  swiftdata.md           (SwiftData — full former swiftdata-pro skill)
  sqlitedata.md          (SQLiteData — full former sqlite-data skill)
  grdb.md                (GRDB — full former grdb skill)
assets/
  swiftdata-pro-icon.png, swiftdata-pro-icon.svg
agents/
  openai.yaml

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.