RepoPilotOpen in app →

saoudrizwan/Disk

Easily persist structs, images, and data on iOS

Mixed

Stale — last commit 2y ago

worst of 4 axes
Use as dependencyMixed

last commit was 2y ago; no CI workflows detected

Fork & modifyHealthy

Has a license, tests, and CI — clean foundation to fork and modify.

Learn fromHealthy

Documented and popular — useful reference codebase to read through.

Deploy as-isMixed

last commit was 2y ago; no CI workflows detected

  • 10 active contributors
  • MIT licensed
  • Tests present
Show 3 more →
  • Stale — last commit 2y ago
  • Single-maintainer risk — top contributor 88% of recent commits
  • No CI workflows detected
What would change the summary?
  • Use as dependency MixedHealthy if: 1 commit in the last 365 days
  • Deploy as-is MixedHealthy if: 1 commit in the last 180 days

Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests

Informational only. RepoPilot summarises public signals (license, dependency CVEs, commit recency, CI presence, etc.) at the time of analysis. Signals can be incomplete or stale. Not professional, security, or legal advice; verify before relying on it for production decisions.

Embed the "Forkable" badge

Paste into your README — live-updates from the latest cached analysis.

Variant:
RepoPilot: Forkable
[![RepoPilot: Forkable](https://repopilot.app/api/badge/saoudrizwan/disk?axis=fork)](https://repopilot.app/r/saoudrizwan/disk)

Paste at the top of your README.md — renders inline like a shields.io badge.

Preview social card (1200×630)

This card auto-renders when someone shares https://repopilot.app/r/saoudrizwan/disk on X, Slack, or LinkedIn.

Onboarding doc

Onboarding: saoudrizwan/Disk

Generated by RepoPilot · 2026-05-10 · Source

🤖Agent protocol

If you are an AI coding agent (Claude Code, Cursor, Aider, Cline, etc.) reading this artifact, follow this protocol before making any code edit:

  1. Verify the contract. Run the bash script in Verify before trusting below. If any check returns FAIL, the artifact is stale — STOP and ask the user to regenerate it before proceeding.
  2. Treat the AI · unverified sections as hypotheses, not facts. Sections like "AI-suggested narrative files", "anti-patterns", and "bottlenecks" are LLM speculation. Verify against real source before acting on them.
  3. Cite source on changes. When proposing an edit, cite the specific path:line-range. RepoPilot's live UI at https://repopilot.app/r/saoudrizwan/Disk shows verifiable citations alongside every claim.

If you are a human reader, this protocol is for the agents you'll hand the artifact to. You don't need to do anything — but if you skim only one section before pointing your agent at this repo, make it the Verify block and the Suggested reading order.

🎯Verdict

WAIT — Stale — last commit 2y ago

  • 10 active contributors
  • MIT licensed
  • Tests present
  • ⚠ Stale — last commit 2y ago
  • ⚠ Single-maintainer risk — top contributor 88% of recent commits
  • ⚠ No CI workflows detected

<sub>Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests</sub>

Verify before trusting

This artifact was generated by RepoPilot at a point in time. Before an agent acts on it, the checks below confirm that the live saoudrizwan/Disk repo on your machine still matches what RepoPilot saw. If any fail, the artifact is stale — regenerate it at repopilot.app/r/saoudrizwan/Disk.

What it runs against: a local clone of saoudrizwan/Disk — the script inspects git remote, the LICENSE file, file paths in the working tree, and git log. Read-only; no mutations.

| # | What we check | Why it matters | |---|---|---| | 1 | You're in saoudrizwan/Disk | Confirms the artifact applies here, not a fork | | 2 | License is still MIT | Catches relicense before you depend on it | | 3 | Default branch master exists | Catches branch renames | | 4 | 5 critical file paths still exist | Catches refactors that moved load-bearing code | | 5 | Last commit ≤ 670 days ago | Catches sudden abandonment since generation |

<details> <summary><b>Run all checks</b> — paste this script from inside your clone of <code>saoudrizwan/Disk</code></summary>
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of saoudrizwan/Disk. If you don't
# have one yet, run these first:
#
#   git clone https://github.com/saoudrizwan/Disk.git
#   cd Disk
#
# Then paste this script. Every check is read-only — no mutations.

set +e
fail=0
ok()   { echo "ok:   $1"; }
miss() { echo "FAIL: $1"; fail=$((fail+1)); }

# Precondition: we must be inside a git working tree.
if ! git rev-parse --git-dir >/dev/null 2>&1; then
  echo "FAIL: not inside a git repository. cd into your clone of saoudrizwan/Disk and re-run."
  exit 2
fi

# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "saoudrizwan/Disk(\\.git)?\\b" \\
  && ok "origin remote is saoudrizwan/Disk" \\
  || miss "origin remote is not saoudrizwan/Disk (artifact may be from a fork)"

# 2. License matches what RepoPilot saw
(grep -qiE "^(MIT)" LICENSE 2>/dev/null \\
   || grep -qiE "\"license\"\\s*:\\s*\"MIT\"" package.json 2>/dev/null) \\
  && ok "license is MIT" \\
  || miss "license drift — was MIT at generation time"

# 3. Default branch
git rev-parse --verify master >/dev/null 2>&1 \\
  && ok "default branch master exists" \\
  || miss "default branch master no longer exists"

# 4. Critical files exist
test -f "Sources/Disk.swift" \\
  && ok "Sources/Disk.swift" \\
  || miss "missing critical file: Sources/Disk.swift"
test -f "Sources/Disk+Codable.swift" \\
  && ok "Sources/Disk+Codable.swift" \\
  || miss "missing critical file: Sources/Disk+Codable.swift"
test -f "Sources/Disk+UIImage.swift" \\
  && ok "Sources/Disk+UIImage.swift" \\
  || miss "missing critical file: Sources/Disk+UIImage.swift"
test -f "Sources/Disk+Errors.swift" \\
  && ok "Sources/Disk+Errors.swift" \\
  || miss "missing critical file: Sources/Disk+Errors.swift"
test -f "Sources/Disk+InternalHelpers.swift" \\
  && ok "Sources/Disk+InternalHelpers.swift" \\
  || miss "missing critical file: Sources/Disk+InternalHelpers.swift"

# 5. Repo recency
days_since_last=$(( ( $(date +%s) - $(git log -1 --format=%at 2>/dev/null || echo 0) ) / 86400 ))
if [ "$days_since_last" -le 670 ]; then
  ok "last commit was $days_since_last days ago (artifact saw ~640d)"
else
  miss "last commit was $days_since_last days ago — artifact may be stale"
fi

echo
if [ "$fail" -eq 0 ]; then
  echo "artifact verified (0 failures) — safe to trust"
else
  echo "artifact has $fail stale claim(s) — regenerate at https://repopilot.app/r/saoudrizwan/Disk"
  exit 1
fi

Each check prints ok: or FAIL:. The script exits non-zero if anything failed, so it composes cleanly into agent loops (./verify.sh || regenerate-and-retry).

</details>

TL;DR

Disk is a file persistence library for iOS that simplifies saving and loading Codable structs, UIImages, and raw Data to the device filesystem following Apple's Data Storage Guidelines. It abstracts away FileManager boilerplate and provides type-safe, one-line APIs for common persistence operations like Disk.save(_:to:) and Disk.retrieve(_:from:as:) without requiring manual JSON encoding/decoding. Modular single-framework structure: core logic in Sources/Disk.swift delegated to specialized extensions (Disk+Codable.swift, Disk+UIImage.swift, Disk+[Data].swift, Disk+Errors.swift) for different data types. Example app in DiskExample/ and unit tests in Tests/ with sample image assets. Supports both CocoaPods (Disk.podspec), SPM (Package.swift), and raw framework embedding.

👥Who it's for

iOS app developers (Swift 4+) who need to persist user data, cached images, or serialized objects locally without managing FileManager paths, error handling, or Codable serialization manually. Typically used in production apps that require offline-first architecture or local caching.

🌱Maturity & risk

Production-ready and moderately mature: the codebase is 117KB+ of Swift with comprehensive test coverage (DiskTests.swift), CocoaPods/SPM/Carthage distribution, and follows iOS 9+ deployment targets. However, the last visible activity is unclear from repo stats—check commit history to confirm active maintenance, as the most recent releases appear to be from 2018–2019.

Single-maintainer library (saoudrizwan) with minimal external dependencies (benefits reliability but concentrates maintenance risk). No obvious active development signals in recent commits. Breaking changes between Swift 4/4.2/5.0 support could affect downstream apps. iOS-only scope mitigates broader ecosystem risk.

Active areas of work

No recent activity signals visible in provided repo metadata. Recommend checking GitHub Issues, PRs, and commit timestamps to determine if the library is actively maintained or in maintenance-only mode.

🚀Get running

git clone https://github.com/saoudrizwan/Disk.git
cd Disk
open Disk.xcworkspace
# In Xcode: select Disk scheme, build (Cmd+B) and run tests (Cmd+U)
# Or use CocoaPods: pod repo update && pod install

Daily commands: Open Disk.xcworkspace in Xcode, select the Disk scheme, and press Cmd+B to build the framework. Run Cmd+U to execute unit tests. The DiskExample app demonstrates usage—open DiskExample/DiskExample.xcodeproj to build and run the sample app on a simulator or device.

🗺️Map of the codebase

  • Sources/Disk.swift — Main API entry point exposing core methods for persisting and retrieving structs, images, and data across all storage operations.
  • Sources/Disk+Codable.swift — Implements Codable-based persistence for custom structs using JSON encoding/decoding; the primary extension for struct serialization.
  • Sources/Disk+UIImage.swift — Handles UIImage persistence logic including PNG compression and file I/O; critical for image storage on iOS.
  • Sources/Disk+Errors.swift — Defines all custom error types thrown by Disk operations; essential for understanding failure modes and error handling patterns.
  • Sources/Disk+InternalHelpers.swift — Low-level file system operations and path management; underpins all read/write operations across the library.
  • Sources/Disk+VolumeInformation.swift — Exposes device storage capacity queries; required for checking available disk space before persistence operations.
  • DiskExample/DiskExample/ViewController.swift — Complete working example demonstrating Codable structs, image persistence, and error handling patterns.

🧩Components & responsibilities

  • Disk (Main API) (Swift, DispatchQueue, FileManager) — Singleton facade exposing save, retrieve, delete, clear, and introspection methods; routes calls to type-specific extensions
    • Failure mode: Returns DiskError if file paths invalid, serialization fails, or disk full; callers must handle Result<T, DiskError>
  • Codable Extension (JSONEncoder, JSON) — Encodes instances to JSON via JSONEncoder and decodes from JSON; handles type-safe serialization

🛠️How to make changes

Add persistence for a new Codable type

  1. Define your struct/class conforming to Codable (DiskExample/DiskExample/Post.swift)
  2. Use Disk.save(_ instance: Name, to: .documents, as: "filename.json") to persist (Sources/Disk+Codable.swift)
  3. Use Disk.retrieve(_ name: Name.self, from: .documents, as: "filename.json") to load (Sources/Disk+Codable.swift)
  4. Handle DiskError thrown by save/retrieve operations (Sources/Disk+Errors.swift)

Add image persistence to your app

  1. Call Disk.save(_ image: UIImage, to: .documents, as: "photo.png") with PNG compression (Sources/Disk+UIImage.swift)
  2. Retrieve with Disk.retrieve(_ name: UIImage.self, from: .documents, as: "photo.png") (Sources/Disk+UIImage.swift)
  3. For multiple images, use batch operations Disk.save(_ images: [UIImage], to: .documents, as: "images") (Sources/Disk+[UIImage].swift)

Check available storage before persistence

  1. Call Disk.totalSpace or Disk.freeSpace to query device storage capacity (Sources/Disk+VolumeInformation.swift)
  2. Compare estimated data size against Disk.freeSpace before calling save() (Sources/Disk+VolumeInformation.swift)

Handle and diagnose persistence errors

  1. Catch DiskError.cantCreateDirectory, .noDataAtLocation, .serialization, or .diskExceedsCapacity (Sources/Disk+Errors.swift)
  2. Use Disk.allFiles(in: .documents) to inspect filesystem state after errors (Sources/Disk+Helpers.swift)
  3. Call Disk.clear(.documents) to reset storage for debugging (Sources/Disk+Helpers.swift)

🔧Why these technologies

  • Codable + JSONEncoder/JSONDecoder — Native Swift serialization framework providing type-safe, zero-dependency struct persistence without external JSON libraries
  • FileManager — Standard iOS API for all file system operations; no external dependencies required for directory traversal, file creation, and I/O
  • UIImage + PNG compression — Native iOS image handling avoiding third-party image libraries; PNG balances compression ratio and decode speed on mobile devices
  • Async/Result-based API — Non-blocking I/O design prevents main-thread blocking during disk operations; Result<T, Error> enforces explicit error handling

⚖️Trade-offs already made

  • JSON-only serialization for Codable (no binary formats like Protobuf)

    • Why: Simplicity and debuggability; JSON files are human-readable and require no code generation
    • Consequence: Slightly larger file sizes and slower encode/decode vs binary formats; acceptable for iOS app persistence use cases
  • PNG compression only for UIImage (no JPEG or WebP support)

    • Why: PNG is lossless and widely compatible; avoids quality loss and simplifies the API surface
    • Consequence: Larger image files than JPEG; tradeoff acceptable for application-internal image storage
  • Synchronous FileManager wrapping with async API surface

    • Why: FileManager itself is synchronous; wrapping in DispatchQueue.global() provides non-blocking on-device concurrency
    • Consequence: Background thread overhead; acceptable because I/O is typically the bottleneck, not CPU dispatch overhead
  • No encryption or access control layers

    • Why: Scope focused on persistence mechanics; encryption delegated to iOS file protection (Data Protection API)
    • Consequence: Unencrypted at rest unless device file protection is enabled; developers must handle sensitive data encryption separately

🚫Non-goals (don't propose these)

  • Does not provide encryption or key management; relies on iOS file protection APIs
  • Does not support networked sync or cloud backup; local filesystem only
  • Does not provide real-time change notifications or KVO observables
  • Does not support custom encoders or heterogeneous type collections in Codable persistence
  • Not a database; does not provide querying, indexing, or transactions

🪤Traps & gotchas

FileManager authorization: Disk assumes app has write access to Documents/Caches directories—no explicit permission checks for restricted access contexts (e.g., App Clips, widgets). Path collisions: Directory names must be unique; passing the same directory name for different data types can cause overwrites. Codable constraints: Custom types must be Codable and acyclic to serialize correctly; complex nested types or circular references will fail silently or raise DiskError.invalidFileExtension. iOS-only: Framework is iOS-specific; macOS, watchOS, tvOS not explicitly supported despite common Foundation APIs. No iCloud sync: Disk saves to local Documents/Caches only; does not integrate with CloudKit or NSUbiquitousItemIdentifier.

🏗️Architecture

💡Concepts to learn

  • Codable Protocol — Disk's primary strength is eliminating Codable boilerplate; understanding Swift's Codable/Encoder/Decoder architecture is essential to using Disk effectively and debugging serialization failures
  • FileManager & iOS Filesystem Hierarchy — Disk wraps FileManager APIs; knowing the difference between Documents, Caches, Temporary directories and iCloud Backup eligibility is critical to following Apple's Data Storage Guidelines correctly
  • iOS Data Storage Guidelines Compliance — Disk is explicitly designed around Apple's guidelines; misunderstanding backup-eligible vs. cache-only storage can cause app rejections or unexpected cloud sync behavior
  • Type-Safe Error Handling (Typed Throws) — Disk's custom DiskError enum with associated values provides granular error context; understanding enum-based error modeling improves robustness of persistence error handling
  • Protocol Extensions & Generics — Disk uses Swift generics and extension-based polymorphism to support Codable, UIImage, and Data arrays without code duplication; this pattern is foundational to Disk's design
  • Image Serialization (PNG/JPG Compression) — Disk's UIImage extension demonstrates lossy vs. lossless image persistence tradeoffs; relevant for optimizing storage size and load times of cached images
  • Volume Space Queries & Disk Quotas — Disk+VolumeInformation.swift provides APIs to check available storage; critical for preemptive cache cleanup and preventing out-of-disk-space crashes
  • realm/realm-swift — Alternative local persistence library for iOS offering object database semantics; users choosing between embedded databases vs. file-based JSON serialization often evaluate both
  • groue/GRDB.swift — SQLite wrapper for iOS persistence; serves similar use cases as Disk but with relational schema and query capabilities instead of flat file storage
  • apple/swift-nio — Apple's async I/O framework; relevant for understanding modern Swift async/await patterns that could enhance Disk's blocking APIs
  • kishikawakatsumi/KeychainAccess — Complementary library for iOS secure credential storage; many apps using Disk for general persistence also need Keychain integration for sensitive data
  • Alamofire/Alamofire — Networking library commonly paired with Disk in iOS apps for downloading remote resources (images, JSON) and caching locally to disk

🪄PR ideas

To work on one of these in Claude Code or Cursor, paste: Implement the "<title>" PR idea from CLAUDE.md, working through the checklist as the task list.

Add comprehensive error handling tests in Tests/DiskTests.swift

Sources/Disk+Errors.swift exists but Tests/DiskTests.swift likely lacks comprehensive coverage of error scenarios (disk full, permission denied, corrupted data, invalid paths). This is critical for a persistence library where error handling directly impacts app reliability. New contributors can add test cases for each error type defined in Disk+Errors.swift.

  • [ ] Review Sources/Disk+Errors.swift to identify all error cases
  • [ ] Add test cases in Tests/DiskTests.swift for: invalid file paths, permission errors, disk space exhaustion, corrupted Codable data, and invalid image formats
  • [ ] Test error recovery and ensure meaningful error messages are returned
  • [ ] Verify tests pass on both simulator and device if applicable

Add async/await API wrapper for Disk operations in Sources/Disk+Async.swift

The library currently appears to lack modern async/await support (Swift 5.5+). Given that Sources/ has multiple extension files (Disk+Codable.swift, Disk+Data.swift, etc.), adding a Disk+Async.swift file with async variants of save/retrieve operations would modernize the API and improve usability in contemporary iOS projects while maintaining backward compatibility.

  • [ ] Create Sources/Disk+Async.swift with async wrapper methods for main operations: save(codable:), retrieve(from:), save(image:), retrieve(image:), save(data:), retrieve(data:)
  • [ ] Ensure async methods dispatch to background threads appropriately to avoid blocking the main thread
  • [ ] Add corresponding async test cases in Tests/DiskTests.swift
  • [ ] Update README.md with async/await usage examples

Add unit tests for Sources/Disk+VolumeInformation.swift coverage

The file Sources/Disk+VolumeInformation.swift exists but there's no evidence of dedicated test coverage in Tests/DiskTests.swift for volume information queries (available space, total capacity, etc.). This is important for apps that need to check disk space before persisting large data, and the functionality should be thoroughly tested.

  • [ ] Review Sources/Disk+VolumeInformation.swift to understand all public methods
  • [ ] Add test cases in Tests/DiskTests.swift that verify: total capacity retrieval, available space calculation, occupied space calculation, and behavior when storage is nearly full
  • [ ] Test edge cases like querying volume info on different storage locations if supported
  • [ ] Verify tests handle potential permission restrictions gracefully

🌿Good first issues

  • Add comprehensive unit tests for Disk+VolumeInformation.swift—no test cases visible in Tests/DiskTests.swift for volume info queries (available space, etc.). Create DiskVolumeTests class with test methods for available space calculation.: Easy
  • Document filepath and directory conventions in Sources/Disk+InternalHelpers.swift; the path sanitization logic and default directory names (Documents vs. Caches) are not explained inline. Add code comments clarifying iOS Data Storage Guidelines compliance.: Easy
  • Add async/await API variants (e.g., Disk.save(codable:to:) wrapped in Task) for Swift 5.5+ compatibility—currently only synchronous blocking APIs exist. Create Disk+Async.swift extension with async save/retrieve methods.: Medium

Top contributors

Click to expand

📝Recent commits

Click to expand
  • d48d67a — Merge pull request #97 from AndrewSB/patch-1 (saoudrizwan)
  • 209c4f1 — README: update locations of the storage to include `. fix applicationSupport (AndrewSB)
  • 76d230e — Update Disk.Directory.pathDescription to have correct value for applicationSupport (AndrewSB)
  • e8f80a1 — Merge pull request #95 from ask-nagata/add-privacy-manifest-file (saoudrizwan)
  • 7a4be33 — Add Privacy Manifest file (ask-nagata)
  • f5254d8 — Revert "Move paid files to .gitroyalty" (saoudrizwan)
  • a8190e8 — Revert "Update README.md" (saoudrizwan)
  • 5b6d0f0 — Update README.md (saoudrizwan)
  • 354be68 — Move paid files to .gitroyalty (saoudrizwan)
  • b0cb4fd — Update version (saoudrizwan)

🔒Security observations

The Disk library is a lightweight iOS persistence framework with a reasonable security posture for general-purpose data storage. The primary concerns are: (1) lack of built-in encryption for persisted data, (2) insufficient documentation on securing sensitive information, and (3) potential directory traversal risks from path handling. The codebase shows no hardcoded secrets, injection vulnerabilities, or infrastructure misconfigurations. Recommendations focus on encryption capabilities, input validation, and guidance for users handling sensitive data.

  • Medium · Potential Insecure File Serialization — Sources/Disk+Codable.swift, Sources/Disk+Data.swift. The Disk library persists data to iOS filesystem using Codable encoding. While generally safe, there is risk if sensitive data (passwords, tokens, PII) is persisted without encryption. The library does not appear to enforce or provide built-in encryption mechanisms for stored data. Fix: Document encryption best practices for users. Consider implementing optional encryption layers using CryptoKit (iOS 13+) or CommonCrypto. Advise users to store sensitive data in Keychain rather than via Disk persistence.
  • Low · Missing Input Validation on File Paths — Sources/Disk+InternalHelpers.swift, Sources/Disk+Helpers.swift. File path handling in Disk+InternalHelpers.swift and Disk+Helpers.swift may not adequately validate or sanitize user-provided directory and file names. This could potentially lead to directory traversal attacks if paths are not properly constrained. Fix: Implement strict validation of file path inputs to prevent directory traversal (e.g., reject paths containing '..' or absolute paths). Ensure paths are constrained to designated app sandbox directories.
  • Low · No Error Message Sanitization — Sources/Disk+Errors.swift. The Disk+Errors.swift file defines error types but there is potential risk if error messages are displayed to users or logged without sanitization, potentially leaking sensitive file system information. Fix: Ensure error messages are user-friendly and do not expose internal file paths or sensitive system information. Use generic error messages in user-facing contexts.
  • Low · Lack of Code Signing Verification — Sources/Disk.swift. No evidence of code signing verification or integrity checks within the library. While the framework itself is distributed via CocoaPods/SPM, integrity of persisted data is not verified against tampering. Fix: Consider implementing optional HMAC or digital signatures for persisted data to detect tampering. Document that app-level security controls should be used for sensitive data.

LLM-derived; treat as a starting point, not a security audit.


Generated by RepoPilot. Verdict based on maintenance signals — see the live page for receipts. Re-run on a new commit to refresh.

Mixed signals · saoudrizwan/Disk — RepoPilot