{"id":35797461,"url":"https://github.com/mihaelamj/cupertino","last_synced_at":"2026-05-31T07:00:35.634Z","repository":{"id":324233233,"uuid":"1096375783","full_name":"mihaelamj/cupertino","owner":"mihaelamj","description":"A local Apple Documentation crawler and MCP server. Written in Swift.","archived":false,"fork":false,"pushed_at":"2026-05-30T21:04:54.000Z","size":41376,"stargazers_count":805,"open_issues_count":95,"forks_count":33,"subscribers_count":3,"default_branch":"main","last_synced_at":"2026-05-30T21:08:35.816Z","etag":null,"topics":["apple-documentation","cli","command-line-tool","developer-tools","documentation-tools","local-server","mcp","mcp-server","model-context-protocol","offline-docs","swift","swiftpm"],"latest_commit_sha":null,"homepage":"","language":"Swift","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mihaelamj.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":"docs/roadmap-maintenance-protocol.md","authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null},"funding":{"github":"mihaelamj"}},"created_at":"2025-11-14T10:33:40.000Z","updated_at":"2026-05-30T21:04:58.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/mihaelamj/cupertino","commit_stats":null,"previous_names":["mihaelamj/appledocsucker","mihaelamj/cupertino"],"tags_count":31,"template":false,"template_full_name":null,"purl":"pkg:github/mihaelamj/cupertino","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mihaelamj%2Fcupertino","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mihaelamj%2Fcupertino/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mihaelamj%2Fcupertino/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mihaelamj%2Fcupertino/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mihaelamj","download_url":"https://codeload.github.com/mihaelamj/cupertino/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mihaelamj%2Fcupertino/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33722156,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-05-31T02:00:06.040Z","response_time":95,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["apple-documentation","cli","command-line-tool","developer-tools","documentation-tools","local-server","mcp","mcp-server","model-context-protocol","offline-docs","swift","swiftpm"],"created_at":"2026-01-07T10:00:54.764Z","updated_at":"2026-05-31T07:00:35.617Z","avatar_url":"https://github.com/mihaelamj.png","language":"Swift","funding_links":["https://github.com/sponsors/mihaelamj"],"categories":["MCP Frameworks and libraries","📚 Projects (2474 total)","Documentation","Developer Tools","📦 Other"],"sub_categories":["Swift","MCP Servers"],"readme":"# 🍎📚 Cupertino\n\n\u003e 🕯️ *v1.3.0 released on 2026-05-31.* Per-source database bundle + read-only databases. The unified `search.db` is split into 8 per-source databases (`apple-documentation.db`, `hig.db`, `apple-archive.db`, `swift-evolution.db`, `swift-org.db`, `swift-book.db`, `apple-sample-code.db`, `packages.db`), each shipped in rollback journal mode so it opens read-only without an `-shm` sidecar. Every query / read / serve connection now opens the databases read-only ([#1194](https://github.com/mihaelamj/cupertino/issues/1194)), so an end user cannot write or delete rows. `databaseVersion` is `1.3.0`: `cupertino setup` downloads `cupertino-databases-v1.3.0.zip` (742 MB) carrying **351,505 documents / 240,543 symbols** in `apple-documentation.db` (2.8 GB, `user_version` 18), plus `packages.db` (1.09 GB, `user_version` 5, 185 packages), `apple-sample-code.db` (192 MB, `samples_schema_version` 4), and the HIG / archive / evolution / org / book databases (all `user_version` 18). Live dashboard at \u003chttps://cupertino.aleahim.com/\u003e. See the [v1.3.0 release notes](https://github.com/mihaelamj/cupertino/releases/tag/v1.3.0).\n\u003e\n\u003e *v1.2.1 (2026-05-23) and v1.2.0 \"ironclad\" (2026-05-20) were the prior releases.* v1.2.0 was the search-quality release (rank-1 accuracy on canonical-lookup queries 52% to 92%); v1.2.1 reached [Source Independence Day](https://github.com/mihaelamj/cupertino/issues/919) (adding a content source is a composition-root-only PR) and closed the [strict-DI + standalone-portability epic](https://github.com/mihaelamj/cupertino/issues/893). Both shipped the unified `cupertino-databases-v1.2.0.zip` bundle (690 MiB, 352,712 documents). See the [v1.2.1](https://github.com/mihaelamj/cupertino/releases/tag/v1.2.1) and [v1.2.0](https://github.com/mihaelamj/cupertino/releases/tag/v1.2.0) notes.\n\n**Apple documentation CLI for humans and MCP server for AI agents**\n\nCupertino is a CLI for human developers and an MCP server for AI agents. Both surfaces use the same local index of Apple documentation, Swift packages, sample code, Human Interface Guidelines, Swift Evolution proposals, and Swift.org pages.\n\n[![Swift 6.3+](https://img.shields.io/badge/Swift-6.3+-orange.svg)](https://swift.org)\n[![macOS 15+](https://img.shields.io/badge/macOS-15+-blue.svg)](https://www.apple.com/macos)\n[![License](https://img.shields.io/badge/license-MIT-green.svg)](LICENSE)\n[![PulseMCP](https://img.shields.io/badge/PulseMCP-listed-blue)](https://www.pulsemcp.com/servers/mihaelamj-cupertino)\n[![LobeHub](https://img.shields.io/badge/LobeHub-listed-purple)](https://lobehub.com/mcp/mihaelamj-cupertino)\n\n![Cupertino Demo](docs/images/cupertino.gif)\n\n## What is Cupertino?\n\nCupertino is a local, structured documentation system for Apple platforms. It:\n\n- **Crawls** Apple Developer documentation, Swift.org, Swift Evolution proposals, Human Interface Guidelines, Apple Archive legacy guides, and Swift package metadata\n- **Indexes** everything into a fast, searchable SQLite FTS5 database with field-weighted BM25 (BM25F) ranking and AST-extracted symbol columns\n- **Runs** as a terminal CLI for developers who want fast local `search`, `read`, `doctor`, and `setup` commands\n- **Serves** the same corpus to AI agents like Claude, ChatGPT, Codex, Cursor, and Copilot via the Model Context Protocol\n- **Provides** offline access to 351,505+ documentation pages / 240,543 symbols across 420+ frameworks (v1.3.0 bundle)\n\n### Why Build This?\n\n- **No more hallucinations**: AI agents get accurate, up-to-date Apple API documentation\n- **Offline development**: Work with full documentation without internet access\n- **Deterministic search**: Same query always returns same results\n- **Local control**: Own your documentation, inspect the database, script workflows\n- **Dual-consumer design**: Use it directly at the terminal or wire it into an MCP-capable AI client\n\n## Quick Start\n\n\u003e **Note:** When building from source, commands must be run from the `Packages` directory. The one-command install works from anywhere.\n\n### Requirements\n\n- macOS 15+ (Sequoia)\n- ~4.2 GB disk space for the full v1.3.0 per-source bundle (apple-documentation.db ~2.8 GB, packages.db ~1.09 GB, apple-sample-code.db ~192 MB, plus the smaller hig / apple-archive / swift-evolution / swift-org / swift-book databases; compressed download is ~742 MB)\n\n*Building from source additionally requires Swift 6.3+ and Xcode 26+ (use `xcrun swift build`, not bare `swift`)*\n\n### Installation\n\n**One-command install (recommended):**\n\n```bash\nbash \u003c(curl -sSL https://raw.githubusercontent.com/mihaelamj/cupertino/main/install.sh)\n```\n\nThis downloads a pre-built, signed, and notarized universal binary, installs it to `/usr/local/bin`, and downloads the documentation databases.\n\n**Or with Homebrew:**\n\n```bash\nbrew tap mihaelamj/tap\nbrew install cupertino\ncupertino setup\n```\n\nAfter `brew install`, you can run `cupertino search \"\u003cquery\u003e\"` at the terminal, or add `cupertino serve` as an MCP server in your AI client config. See [docs/DEPLOYMENT.md](docs/DEPLOYMENT.md) for distribution notes and the MCP client sections below for Claude, Codex, Cursor, VS Code, and other hosts.\n\n**Or build from source:**\n\n```bash\ngit clone https://github.com/mihaelamj/cupertino.git\ncd cupertino\n\n# Using Makefile (recommended)\nmake build                       # Build release binary\nsudo make install                # Install to /usr/local/bin\n\n# Or using Swift Package Manager directly\ncd Packages\nswift build -c release\nsudo ln -sf \"$(pwd)/.build/release/cupertino\" /usr/local/bin/cupertino\n```\n\n### Two Ways to Use the Same Index\n\n**Human CLI example:**\n\n```text\n$ cupertino search \"NavigationStack\" --format text --limit 2\nQuestion: NavigationStack\nSearched: apple-docs, samples, swift-evolution, swift-org, swift-book, packages\n\n======================================================================\n[1] NavigationStack  •  source: apple-docs  •  score: 0.0324\n    apple-docs://swiftui/documentation_swiftui_navigationstack\n----------------------------------------------------------------------\nA view that displays a root view and enables navigation to additional views.\n\n▶ Read full: cupertino read \"apple-docs://swiftui/documentation_swiftui_navigationstack\" --source apple-docs\n\n----------------------------------------------------------------------\nSee also -- drill into one source:\n  cupertino search \"NavigationStack\" --source apple-docs\n  cupertino search \"NavigationStack\" --source samples\n\n💡 Narrow with --source \u003cname\u003e: apple-docs, samples, hig, apple-archive, swift-evolution, swift-org, swift-book, packages\n💡 Filter by platform: --platform iOS --min-version 16.0  (or macOS / tvOS / watchOS / visionOS)\n```\n\n**MCP tool-call example:**\n\n```json\n{\n  \"name\": \"search\",\n  \"arguments\": {\n    \"query\": \"NavigationStack\",\n    \"source\": \"apple-docs\",\n    \"limit\": 2\n  }\n}\n```\n\nBoth examples query the same local databases. The CLI prints a terminal-friendly result with scores and follow-up commands; the MCP server returns structured tool results that an AI client can read, cite, and follow with `read_document`.\n\n**Demo Video:** [Watch on YouTube](https://youtu.be/B-mRdainTMA)\n\n### Quick Reference\n\n```bash\n# Quick Setup (Recommended) - download pre-built databases (~30 seconds)\ncupertino setup                      # Download databases from GitHub\ncupertino search \"NavigationStack\" --format text --limit 5\ncupertino read \"apple-docs://swiftui/documentation_swiftui_navigationstack\" --source apple-docs --format markdown\ncupertino doctor                     # Check local database health\ncupertino serve                      # Start MCP server\n\n# Alternative: Build from GitHub (~45 minutes)\ncupertino save --remote              # Stream and build locally\n\n# Or fetch documentation yourself\ncupertino fetch --source apple-docs          # Apple Developer Documentation\ncupertino fetch --source swift-org         # Swift.org documentation\ncupertino fetch --source swift-evolution     # Swift Evolution proposals\ncupertino fetch --source packages      # Swift package metadata + GitHub archives\ncupertino fetch --source apple-sample-code          # Sample code from Apple (Apple CDN, no auth)\ncupertino fetch --source samples       # Sample code from GitHub (recommended)\ncupertino fetch --source apple-archive       # Apple Archive programming guides\ncupertino fetch --source hig           # Human Interface Guidelines\ncupertino fetch --source availability  # Platform availability data\ncupertino fetch --source all           # All types in parallel\n\n# Build indexes\ncupertino save --all                  # Build every source DB (from local files)\ncupertino save --remote              # Build from GitHub (no local files needed)\ncupertino save --source samples                      # Index sample code for search\n\n# Start server\ncupertino                            # Start MCP server (default command)\ncupertino serve                      # Start MCP server (explicit)\n```\n\n### Instant Setup (Recommended)\n\n```bash\n# Download pre-built databases from GitHub (~30 seconds)\ncupertino setup\n\n# Start MCP server\ncupertino serve\n```\n\n\u003e **Note:** `cupertino setup --force` is no longer valid (the flag was removed in v1.2.0). `cupertino setup` overwrites by default; pass `--keep-existing` to skip the download when databases are already installed.\n\n### Alternative: Build from GitHub\n\n```bash\n# Stream and build locally (~45 minutes)\n# Use this if you want to build the database yourself\ncupertino save --remote\n\n# Start MCP server\ncupertino serve\n```\n\n### Manual Setup (Advanced)\n\n```bash\n# Download Apple documentation (~12+ days for ~404,000+ raw pages, indexed down to ~351,505)\n# Takes time due to 0.05s default delay between requests\ncupertino fetch --source apple-docs --max-pages 15000\n\n# Download Swift Evolution proposals (~2-5 minutes)\ncupertino fetch --source swift-evolution\n\n# Download sample code from GitHub (~4 minutes, 619 projects)\ncupertino fetch --source samples\n\n# Build search index (~2-5 minutes)\ncupertino save --all\n```\n\n### Use with Claude Desktop\n\n1. **Configure Claude Desktop** - Edit `~/Library/Application Support/Claude/claude_desktop_config.json`:\n\n```json\n{\n  \"mcpServers\": {\n    \"cupertino\": {\n      \"command\": \"/usr/local/bin/cupertino\",\n      \"args\": [\"serve\"]\n    }\n  }\n}\n```\n\n\u003e **Note:** Use `/opt/homebrew/bin/cupertino` for Homebrew on Apple Silicon, `/usr/local/bin/cupertino` for Intel or manual install. Run `which cupertino` to find your path.\n\n2. **Restart Claude Desktop**\n\n3. **Ask Claude about Apple APIs:**\n   - \"Search for SwiftUI documentation\"\n   - \"What does Swift Evolution proposal SE-0001 propose?\"\n   - \"List available frameworks\"\n\n### Use with Claude Code\n\nIf you're using [Claude Code](https://code.claude.com/docs/en/overview), you can add Cupertino as an MCP server with a single command:\n\n```bash\nclaude mcp add cupertino --scope user -- $(which cupertino)\n```\n\nThis registers Cupertino globally for all your projects. Claude Code will automatically have access to Apple documentation search.\n\n### Use with OpenAI Codex\n\nIf you're using [OpenAI Codex](https://github.com/openai/codex), add Cupertino with:\n\n```bash\ncodex mcp add cupertino -- $(which cupertino) serve --no-reap\n```\n\nOr add directly to `~/.codex/config.toml`:\n\n```toml\n[mcp_servers.cupertino]\ncommand = \"/opt/homebrew/bin/cupertino\"  # Homebrew on Apple Silicon\n# command = \"/usr/local/bin/cupertino\"   # Intel Mac or manual install\nargs = [\"serve\", \"--no-reap\"]\n```\n\n\u003e **Why `--no-reap`?** Codex spawns a fresh `cupertino serve` per tool\n\u003e call. Without `--no-reap`, each new instance kills its predecessor as\n\u003e a stale sibling, and the in-flight transport closes (`Transport closed`\n\u003e error on every tool call; see #280). Claude Desktop / Cursor users\n\u003e keep the default (reap on) so MCP-host config reloads don't leak\n\u003e orphan servers.\n\u003e\n\u003e Equivalent env-var form: `CUPERTINO_DISABLE_REAPER=1` in\n\u003e `[mcp_servers.cupertino.env]`.\n\n\u003e **Tip:** Run `which cupertino` to find your installation path.\n\n### Use with Cursor\n\nAdd to `.cursor/mcp.json` in your project (or `~/.cursor/mcp.json` for global access):\n\n```json\n{\n  \"mcpServers\": {\n    \"cupertino\": {\n      \"command\": \"/opt/homebrew/bin/cupertino\",\n      \"args\": [\"serve\"]\n    }\n  }\n}\n```\n\n### Use with VS Code (GitHub Copilot)\n\nAdd to `.mcp.json` in your workspace:\n\n```json\n{\n  \"mcpServers\": {\n    \"cupertino\": {\n      \"type\": \"stdio\",\n      \"command\": \"/opt/homebrew/bin/cupertino\",\n      \"args\": [\"serve\"]\n    }\n  }\n}\n```\n\n### Use with GitHub Copilot for Xcode\n\n[GitHub Copilot for Xcode](https://github.com/github/CopilotForXcode) supports MCP servers via Agent Mode. In the app, go to the **Tools** tab → **MCP** sub-tab → **MCP Configuration** → **Edit Config**, or edit `~/.config/github-copilot/xcode/mcp.json` directly:\n\n```json\n{\n  \"servers\": {\n    \"cupertino\": {\n      \"type\": \"stdio\",\n      \"command\": \"/opt/homebrew/bin/cupertino\",\n      \"args\": [\"serve\"]\n    }\n  }\n}\n```\n\n### Use with Zed\n\nAdd to your Zed `settings.json`:\n\n```json\n{\n  \"context_servers\": {\n    \"cupertino\": {\n      \"command\": \"/opt/homebrew/bin/cupertino\",\n      \"args\": [\"serve\"]\n    }\n  }\n}\n```\n\n### Use with Windsurf\n\nAdd to `~/.codeium/windsurf/mcp_config.json`:\n\n```json\n{\n  \"mcpServers\": {\n    \"cupertino\": {\n      \"command\": \"/opt/homebrew/bin/cupertino\",\n      \"args\": [\"serve\"]\n    }\n  }\n}\n```\n\n### Use with opencode\n\nAdd to `opencode.jsonc`:\n\n```json\n{\n  \"mcp\": {\n    \"cupertino\": {\n      \"type\": \"local\",\n      \"command\": [\"/opt/homebrew/bin/cupertino\", \"serve\"]\n    }\n  }\n}\n```\n\n\u003e **Note:** All examples use `/opt/homebrew/bin/cupertino` (Homebrew on Apple Silicon). Use `/usr/local/bin/cupertino` for Intel Macs or manual installs. Run `which cupertino` to find your path.\n\n### Use as an Agent Skill (No Server Required)\n\nCupertino can also be used as a stateless CLI skill without running an MCP server. This is useful for agents that support the [Agent Skills](https://agentskills.io) specification.\n\n**Prerequisites:**\n\nInstall cupertino and download the databases first:\n```bash\n# Install via Homebrew or from source (see Installation above)\ncupertino setup\n```\n\n**Option A: Install with OpenSkills (Recommended)**\n\n[OpenSkills](https://github.com/numman-ali/openskills) is a universal skills loader that works with Claude Code, Cursor, Windsurf, Aider, and other AI coding agents.\n\n```bash\n# Install the cupertino skill from GitHub\nnpx openskills install mihaelamj/cupertino\n\n# Sync to update AGENTS.md\nnpx openskills sync\n```\n\nFor global installation (available in all projects):\n```bash\nnpx openskills install mihaelamj/cupertino --global\n```\n\nFor multi-agent setups (installs to `.agent/skills/` instead of `.claude/skills/`):\n```bash\nnpx openskills install mihaelamj/cupertino --universal\n```\n\n**Option B: Install as a Claude Code Plugin**\n\nInside a Claude Code session, add the cupertino marketplace:\n```\n/plugin marketplace add mihaelamj/cupertino\n```\n\nThen enable the plugin from the marketplace.\n\n**Option C: Manual Installation**\n\nCopy the skill definition to your project or global skills directory:\n```bash\n# Clone this repo\ngit clone https://github.com/mihaelamj/cupertino.git\n\n# For a single project\nmkdir -p .claude/skills/cupertino\ncp cupertino/skills/cupertino/SKILL.md .claude/skills/cupertino/\n\n# Or for global use with Claude Code\nmkdir -p ~/.claude/skills/cupertino\ncp cupertino/skills/cupertino/SKILL.md ~/.claude/skills/cupertino/\n```\n\n**How It Works:**\n\nThe skill uses the CLI directly with JSON output, no server process needed:\n\n```bash\n# Search documentation\ncupertino search \"SwiftUI View\" --format json\n\n# Filter by source\ncupertino search \"NavigationStack\" --source apple-docs --format json\ncupertino search \"button styles\" --source samples --format json\n\n# Read a document\ncupertino read \"apple-docs://swiftui/documentation_swiftui_view\" --format json\n\n# List frameworks\ncupertino list-frameworks --format json\n\n# List sample projects\ncupertino list-samples --framework swiftui --format json\n```\n\nAll commands support `--format json` for structured output that agents can parse.\n\n**Available Sources:**\n- `apple-docs` - Official Apple documentation (~351,505 pages indexed in v1.3.0)\n- `samples` - Apple sample code projects\n- `hig` - Human Interface Guidelines\n- `swift-evolution` - Swift Evolution proposals\n- `swift-org` - Swift.org documentation\n- `swift-book` - The Swift Programming Language book\n- `apple-archive` - Legacy programming guides\n- `packages` - Swift package documentation\n\n### What You Get\n\nOnce configured, Claude Desktop can search your local documentation:\n\n**Search Results Example:**\n```\n# Search Results for \"SwiftUI\"\n\nFound **20** results:\n\n## 1. NSHostingView | Apple Developer Documentation\n- **Framework:** `swiftui`\n- **URI:** `apple-docs://swiftui/documentation_swiftui_nshostingview`\n- **Score:** 1.82\n\nAn AppKit view that hosts a SwiftUI view hierarchy.\n\n## 2. UIHostingController | Apple Developer Documentation\n- **Framework:** `swiftui`\n- **URI:** `apple-docs://swiftui/documentation_swiftui_uihostingcontroller`\n\nA UIKit view controller that manages a SwiftUI view hierarchy.\n...\n```\n\n**Framework Statistics:**\n| Framework | Documents |\n|-----------|----------:|\n| Kernel | 39,396 |\n| Matter | 24,320 |\n| Swift | 17,466 |\n| AppKit | 12,443 |\n| Foundation | 12,423 |\n| UIKit | 11,158 |\n| Accelerate | 9,114 |\n| SwiftUI | 7,062 |\n| ... | ... |\n| **420+ Frameworks** | **351,505** |\n\n## Core Features\n\n### 1. Multi-Source Documentation Fetching\n\n- **Apple Developer Documentation** (~351,505 indexed pages in the v1.3.0 bundle)\n  - JavaScript-aware rendering via WKWebView\n  - HTML to Markdown conversion\n  - Smart change detection\n\n- **Swift Evolution Proposals** (~400 proposals)\n  - GitHub-based fetching\n  - Markdown format\n  - Fast downloads\n\n- **Swift.org Documentation**\n  - Official Swift language docs\n  - Clean HTML structure\n\n- **Swift Package Metadata**\n  - Priority package catalogs\n  - README files\n\n- **Apple Sample Code** (619 projects)\n  - Two fetch methods: GitHub (recommended) or Apple website\n  - Full-text search across all source files\n  - 18,000+ indexed Swift files\n\n- **Apple Archive Legacy Guides** (~75 pages)\n  - Pre-2016 programming guides (Core Animation, Quartz 2D, Core Text, etc.)\n  - Deep conceptual knowledge not in modern docs\n  - Excluded from search by default (use `--include-archive`)\n\n- **Human Interface Guidelines**\n  - Apple's official design guidelines for all platforms\n  - Covers iOS, macOS, watchOS, visionOS, and tvOS\n  - Design patterns, components, foundations, and best practices\n\n### 2. Bundled Resources\n\nCupertino includes pre-indexed catalog data bundled directly into the application:\n\n- **Swift Packages Catalog** (183 Apple-official packages with full source + metadata in `packages.db`; the previous 9,699-entry embedded URL list was removed in #194; `packages.db` is now the canonical corpus, shipped via `cupertino setup`)\n  - Curated from Swift Package Index + GitHub API\n  - Includes package metadata, stars, licenses, descriptions, deployment-target platforms, **and** authored `swift-tools-version` (#225)\n  - Updated by re-running `cupertino fetch --source packages` then `cupertino save --source packages`\n\n- **Sample Code Catalog** (619 entries)\n  - Apple's official sample code projects\n  - Includes titles, descriptions, frameworks, download URLs\n  - Bundled because Apple's catalog doesn't change frequently\n\n- **Priority Packages** (36 curated packages)\n  - Apple official packages (31) + essential ecosystem packages (5)\n  - High-priority Swift packages for quick access\n\nThese catalogs are indexed during `cupertino save --all` and enable instant search without requiring multi-hour downloads. You can still fetch package READMEs and sample code separately via `cupertino fetch` if needed.\n\n### 3. Full-Text Search Engine\n\n- **Technology**: SQLite FTS5 with field-weighted BM25 (BM25F, Robertson/Zaragoza/Taylor 2004) over a 9-column index (`uri`, `source`, `framework`, `language`, `title`, `content`, `summary`, `symbols`, `symbol_components`). Title 10×, AST-extracted symbols 5×, summary 3×, framework 2×, CamelCase-split symbol components 1.5×.\n- **AST-aware**: a Swift source extractor pulls identifiers out of every embedded code block and the page declaration, denormalizes them into a `symbols` column, and feeds them into BM25F so a query like `Task` ranks the Swift `Task` struct above prose mentions of the word \"task\".\n- **smart-query**: `cupertino search` (and the underlying `Search.SmartQuery` API) fans the question across every source in parallel and fuses per-source rankings via reciprocal rank fusion (RRF, k=60, Cormack/Clarke/Büttcher 2009). One dead source never takes the whole query down.\n- **Features**:\n  - Porter stemming (e.g., \"running\" matches \"run\")\n  - Framework filtering\n  - Platform availability filtering (iOS/macOS version)\n  - Snippet generation\n  - Sub-100ms query performance\n- **Size**: ~2.8 GB apple-documentation.db + ~1.09 GB packages.db + ~192 MB apple-sample-code.db + the smaller hig / apple-archive / swift-evolution / swift-org / swift-book databases for full documentation (351,505 documents / 240,543 symbols across 420+ frameworks, v1.3.0 per-source bundle)\n- **Storage**: Database must be on local filesystem - SQLite does not work reliably on network drives (NFS/SMB)\n\n### 4. Model Context Protocol Server\n\n- **Resources**: Direct access to documentation pages\n  - `apple-docs://{framework}/{page}`\n  - `swift-evolution://{proposal-id}`\n  - `hig://{category}/{page}`\n- **Tools**: Search and read capabilities for AI agents\n  - **Documentation Tools** (requires `cupertino save --all`):\n    - `search` - **Unified full-text search** across every indexed source: Apple Developer Documentation, sample code, Human Interface Guidelines, Apple Archive, Swift Evolution, swift.org, the Swift Book, and Swift package metadata. Replaces the pre-[#239](https://github.com/mihaelamj/cupertino/issues/239) per-source tools (`search_docs`, `search_hig`, `search_samples`, `search_all`).\n      - Parameters: `query` (required), `source` (optional: `all`, `apple-docs`, `samples`, `hig`, `apple-archive`, `swift-evolution`, `swift-org`, `swift-book`, `packages`), `framework`, `language`, `include_archive`, `limit`, `min_ios`, `min_macos`, `min_tvos`, `min_watchos`, `min_visionos`, `min_swift`, `apple_imports` (all optional)\n      - Platform filtering (#226, #732): the 5 `min_*` parameters apply on every source whose data carries platform-availability metadata (apple-docs, apple-archive, packages, swift-evolution, swift-org, swift-book, samples). Multi-platform values AND-combine (e.g. `min_ios=18.0` + `min_macos=14.0` keeps only results that satisfy both). HIG content has no version axis and the filter doesn't apply there; the response prefixes a `platform_filter_partial` notice when HIG contributes to the result set so AI clients know the filter was non-uniform. Malformed `min_*` values (`\"v18.0\"`, `\"\"`, `\"18..0\"`) are rejected at the MCP boundary with a clear `invalidArgument` error frame instead of silently no-oping.\n    - `list_frameworks` - List indexed frameworks with document counts\n    - `read_document` - Read document by URI with format option\n      - Parameters: `uri` (required), `format` (optional: `json` or `markdown`, default: `json`)\n      - JSON format returns the full structured document data (recommended for AI)\n      - Markdown format returns rendered content for human reading\n  - **Sample Code Tools** (requires `cupertino save --source samples`):\n    - `list_samples` - List indexed sample projects\n    - `read_sample` - Read sample project README and metadata\n    - `read_sample_file` - Read source file from a sample project\n    - (For sample-code search, use the unified `search` tool above with `source: samples`.)\n  - **Semantic Search Tools** (AST-powered, [#81](https://github.com/mihaelamj/cupertino/issues/81)):\n    - `search_symbols` - Search by symbol kind (class, struct, actor, function) and name\n    - `search_property_wrappers` - Find `@State`, `@Observable`, `@MainActor` usage patterns\n    - `search_concurrency` - Find `async`/`await`, actor, `Sendable` patterns\n    - `search_conformances` - Find types by protocol conformance (`View`, `Codable`, etc.)\n    - `search_generics` - Find symbols by generic constraint (`Sendable`, `Hashable`, `View`)\n    - `get_inheritance` - Walk class inheritance chains (ancestors / descendants)\n\n### 5. Intelligent Crawling\n\n- **Resumable**: Continue interrupted crawls from saved state\n- **Change Detection**: Skip unchanged pages on updates\n- **Respectful**: 0.05s default delay between requests (configurable)\n- **Deduplication**: Automatic URL queue management\n- **Priority Queues**: Important content fetched first\n\n## Commands\n\n| Command | Description |\n|---------|-------------|\n| `cupertino` | Start MCP server (default) |\n| `cupertino setup` | Download pre-built databases from GitHub |\n| `cupertino serve` | Start MCP server |\n| `cupertino fetch` | Download documentation |\n| `cupertino save --all` | Build search index |\n| `cupertino search` | Search documentation from CLI |\n| `cupertino read` | Read full document by URI |\n| `cupertino doctor` | Check server health |\n| `cupertino save --source samples` | Index sample code for search |\n| `cupertino cleanup` | Clean up sample code archives |\n\nSee [docs/commands/](docs/commands/) for detailed usage and options.\n\n## Architecture\n\nCupertino uses an **[ExtremePackaging](https://aleahim.com/blog/extreme-packaging/)** architecture: 49 strict-producer SPM targets across 63 source packages. See [`docs/ARCHITECTURE.md`](docs/ARCHITECTURE.md) for the full breakdown and [`docs/package-import-contract.md`](docs/package-import-contract.md) for the strict per-target import rules.\n\n```\nFoundation tier:   SharedConstants, LoggingModels, MCPCore, MCPSharedTools, Resources\nInfrastructure:    ASTIndexer, Diagnostics, Logging (concrete, composition-root only)\nProducers:         Crawler, Core, Search, SampleIndex, Services,\n                   AppleConstraintsKit, Availability, Cleanup, and more\nOperation packs:   Distribution (setup), Diagnostics (doctor),\n                   Indexer (save), Ingest (fetch)\nMCP layer:         MCPSupport, MCPClient, SearchToolProvider\nFront doors:       CLI (cupertino), TUI (cupertino-tui)\nAuxiliary:         MockAIAgent, ReleaseTool, RemoteSync, TestSupport\n```\n\n### Data Flow\n\n```\n1. Fetch:  cupertino fetch --source apple-docs\n   ↓\n   WKWebView → Apple JSON API response → JSON files → disk (~/.cupertino/docs/)\n\n2. Save:   cupertino save --all\n   ↓\n   JSON files → parse + AST extract → per-source SQLite FTS5 indexes (~/.cupertino/apple-documentation.db, hig.db, …)\n\n3. Serve:  cupertino serve\n   ↓\n   MCP Server (stdio) ← JSON-RPC ← Claude Desktop\n   ↓\n   DocsResourceProvider + CupertinoSearchToolProvider\n```\n\n### Key Design Principles\n\n- **Swift 6.3 Concurrency**: 100% strict concurrency checking with actors and async/await\n- **Value Semantics**: Immutable structs by default, Sendable conformance\n- **Actor Isolation**: @MainActor for WKWebView, actors for shared state\n- **Explicit Dependencies**: No singletons, clear dependency injection\n- **Separation of Concerns**: Crawling → Indexing → Serving as distinct phases\n\n### Published Packages\n\nCupertino factors three reusable, independently-versioned Swift packages out of the monorepo. Each is its own public repository, depended on by tag (`from: \"0.1.0\"`), Foundation-only, and built so an external consumer can adopt it without pulling in cupertino's engine:\n\n| Package | Repo | What it is |\n|---|---|---|\n| **SwiftMCPCore** | [mihaelamj/SwiftMCPCore](https://github.com/mihaelamj/SwiftMCPCore) | Neutral MCP wire types (the JSON-RPC + protocol value types). Not cupertino-specific; a general MCP building block. |\n| **SwiftMCPClient** | [mihaelamj/SwiftMCPClient](https://github.com/mihaelamj/SwiftMCPClient) | Neutral, transport-injectable MCP client (`Client.MCP` seam, `MCPClient` actor, subprocess transport). Depends on SwiftMCPCore. |\n| **CupertinoDataKit** | [mihaelamj/CupertinoDataKit](https://github.com/mihaelamj/CupertinoDataKit) | Cupertino's public **read contract**: the documentation + sample-code read protocols (`Search.DocumentReading` core, `Search.SymbolReading` refinement, `Search.Database` composition, `Sample.Index.Reader`) plus every value type they return (`Search.Result`, `MatchedSymbol`, `PlatformAvailability`, `DocumentFormat`, `SymbolSearchResult`, inheritance types, `URIResource`, `FrameworkAvailability`, `PlatformMinima`/`PlatformFilter`, `Sample.Index.Project`/`File`/`FileSearchResult`, `Sample.Search.Query`/`Result`). Protocols + value types only, zero implementation. Cupertino's engine conforms to it server-side; an embedded/in-process reader (e.g. an iOS app) conforms a different implementation. It is the single source of truth for these types: cupertino's foundation tier re-exports it (`@_exported import CupertinoDataKit`), so in-repo code uses the `Search.*` / `Sample.*` namespaces unchanged. |\n\n## Development\n\n### Build System\n\n```bash\n# Show all available commands\nmake help\n\n# Common tasks\nmake build                  # Build release binaries\nsudo make install           # Install to /usr/local/bin\nsudo make update            # Rebuild and reinstall\nmake test                   # Run all tests\nmake clean                  # Clean build artifacts\n\n# Development workflow\nmake test-unit              # Fast unit tests only\nmake test-integration       # All tests (includes network calls)\nmake format                 # Format code with SwiftFormat\nmake lint                   # Lint with SwiftLint\n```\n\n### Testing\n\n**Test Suite:**\n- 2,989 test functions across 327 test files (457 `@Suite`s); parameterized `@Test(arguments:)` cases expand further at runtime\n- Swift Testing framework (`@Test`, `@Suite`, `#expect`) with `withDependencies` for injection\n- Includes unit tests, integration tests (real WKWebView + real Apple docs), and formatter tests\n\n**Test Categories:**\n- Web Crawl Tests - Real Apple documentation fetching\n- Fetch Command Tests - Package/code downloading\n- Save Command Tests - Search index building\n- MCP Tests - Server health, tool/resource providers\n- Core Tests - Search, logging, state management\n\n### Logging\n\nCupertino uses **os.log** for structured logging:\n\n```bash\n# View all logs\nlog show --predicate 'subsystem == \"com.cupertino.cli\"' --last 1h\n\n# View specific category\nlog show --predicate 'subsystem == \"com.cupertino.cli\" AND category == \"crawler\"' --last 1h\n\n# Stream live logs\nlog stream --predicate 'subsystem == \"com.cupertino.cli\"'\n```\n\n**Categories**: crawler, mcp, search, cli, transport, evolution, samples, package-downloader, archive, hig\n\n\u003e **MCP JSON-RPC wire traffic is on stderr, not os.log.** The stdio transport writes each request and response message (the `→`/`←` wire traffic) to **stderr**, because stdout carries the protocol itself. To watch the wire traffic, capture the server's stderr (`cupertino serve 2\u003e/tmp/cupertino-mcp.log`) or open your MCP client's server-output panel. MCP server lifecycle and diagnostic messages (index availability, load failures) are logged to os.log under the `mcp` category, so the `com.cupertino.cli` predicate above still surfaces them.\n\n## Performance\n\n| Operation | Time | Size |\n|-----------|------|------|\n| Build CLI | 10-15s | 4.3MB |\n| Crawl ~414,000+ raw pages (post-dedup 351,505 indexed, v1.3.0) | 12+ days | 2-3GB |\n| Swift Evolution | 2-5 min | 429 proposals |\n| Swift.org docs | 5-10 min | 501 pages |\n| Build search index (full Apple docs corpus) | ~12h | ~2.8 GB apple-documentation.db (+ per-source siblings) |\n| Search query | \u003c100ms | - |\n\n### Why Crawling Takes 12+ Days\n\nThe crawler uses a **0.05 second default delay between each request** (configurable):\n- 412,000 raw pages × 0.05s = ~5.7 hours for delay alone; WKWebView rendering time per page makes real wall-clock significantly longer\n- Plus page rendering, parsing, and saving time\n- Crawl must reach depth 21+ to get all documentation\n- **Total: ~12+ days for initial full crawl**\n\nUse `cupertino setup` to download pre-built databases instead (~30 seconds).\n\nThis is a **one-time operation**. Incremental updates use change detection to skip unchanged pages and complete much faster.\n\n## Example Use Cases\n\n### 1. Offline Documentation Archive\n\n```bash\n# Download everything for offline access\ncupertino fetch --source apple-docs --max-pages 15000\ncupertino fetch --source swift-evolution\ncupertino save --all\n```\n\n### 2. Framework-Specific Research\n\n```bash\n# Just SwiftUI documentation\ncupertino fetch --source apple-docs \\\n  --start-url \"https://developer.apple.com/documentation/swiftui\" \\\n  --max-pages 500\n```\n\n### 3. AI-Assisted Development\n\n```bash\n# Serve documentation to Claude\ncupertino serve\n\n# Then ask Claude: \"How do I use @Observable in SwiftUI?\"\n```\n\n### 4. Custom Documentation Workflows\n\n```bash\n# Multiple sources with custom paths\ncupertino fetch --source apple-docs --output-dir ~/docs/apple\ncupertino fetch --source swift-evolution --output-dir ~/docs/evolution\ncupertino save --base-dir ~/docs\ncupertino serve --base-dir ~/docs\n```\n\n`cupertino save --all` emits diagnostic lines at startup so long-running re-index jobs surface their state upfront in any captured log:\n\n```\n💾 Output: \u003cresolved-search-db-path\u003e\n🗑️  Removing existing database for clean re-index...   (only if one was present)\n🗄️  Initializing search database...\n✅ Swift Evolution directory found at \u003cpath\u003e          (per detected optional source)\n✅ Apple Archive directory found at \u003cpath\u003e\nℹ️  HIG directory not found at \u003cpath\u003e, skipping       (per missing optional source)\n...\n```\n\nOptional sources (Swift Evolution / Swift.org / Apple Archive / HIG) are auto-detected under `--base-dir` using the standard layout (`\u003cbase\u003e/swift-evolution`, `\u003cbase\u003e/swift-org`, `\u003cbase\u003e/archive`, `\u003cbase\u003e/hig`) or symlinks at those paths; explicit `--\u003csource\u003e-dir` flags override the auto-detection.\n\n## Documentation\n\n- **[CONTRIBUTING.md](CONTRIBUTING.md)** - Build, test, contribute, and release workflow\n- **[docs/PRINCIPLES.md](docs/PRINCIPLES.md)** - Engineering principles (lossless URIs, no content lost at the door, 10x scale headroom)\n- **[docs/ARCHITECTURE.md](docs/ARCHITECTURE.md)** - Technical deep-dives (Concurrency, MCP, WKWebView testing)\n- **[docs/DEPLOYMENT.md](docs/DEPLOYMENT.md)** - Homebrew distribution and CI/CD setup\n- **[docs/commands/](docs/commands/)** - Command-specific documentation\n- **[docs/tools/](docs/tools/)** - MCP-tool-specific documentation\n- **[docs/roadmap-maintenance-protocol.md](docs/roadmap-maintenance-protocol.md)** - Maintainer roadmap update protocol\n\n### Command Documentation\n\nEach command has detailed documentation:\n- [docs/commands/fetch/](docs/commands/fetch/) - Download documentation\n- [docs/commands/save/](docs/commands/save/) - Build search indexes\n- [docs/commands/serve/](docs/commands/serve/) - Start MCP server\n- [docs/commands/search/](docs/commands/search/) - Search documentation from CLI\n- [docs/commands/doctor/](docs/commands/doctor/) - Check server health\n\n## Contributing\n\nIssues and pull requests are welcome! I'd love to hear how you're using Cupertino with your AI workflow.\n\nFor questions and discussion, use [GitHub Discussions](https://github.com/mihaelamj/cupertino/discussions).\n\nI prefer collaboration over competition. If you're working on something similar, let's find ways to work together.\n\nDon't hesitate to submit a PR because of code style. I'd rather have your contribution than perfect formatting.\n\nBy participating in this project you agree to abide by the [Contributor Covenant Code of Conduct](https://www.contributor-covenant.org/).\n\nFor development setup, see [CONTRIBUTING.md](CONTRIBUTING.md).\n\n## Project Status\n\n**Released:** v1.2.0 \"ironclad\" on 2026-05-20. `databaseVersion` is `1.2.0`; `cupertino setup` downloads the v1.2.0 bundle (352,712 documents across 420 frameworks, 0 poison rows under all 13 audit categories, schema `user_version = 18`).\n\nHeadline jump from v1.1.0: **rank-1 accuracy on canonical-lookup queries went from 52% to 92%** on the 50-query Phase 1 corpus. **30 / 30 modern Swift wins on the deprecation pair corpus** (was 27 / 30). **Zero regressions across 110 paired queries.** Live dashboard at \u003chttps://cupertino.aleahim.com/\u003e; full release write-up at `docs/release-writeup-v1.2.0.md`; harness at `scripts/eval/search-quality-phase1.py` (reproducible: two runs against the same `(binary, database)` pair produce byte-identical per-query ranks).\n\n**Previously released:** v1.1.0 on 2026-05-14 (refactor release: namespacing + Crawler extract + DI epic kickoff; 285,735 documents, schema 13). v1.0.2 on 2026-05-11 (URL canonicalization + re-indexed bundle, 277,640 documents).\n\n- ✅ All core functionality working\n- ✅ 350+ test functions across 230+ test files (2,408 / 347 suites green at v1.2.0 ship)\n- ✅ 0 lint violations\n- ✅ Swift 6.3 compliant with 100% strict concurrency checking\n- ✅ All production bugs resolved at ship time\n- ✅ Search quality measured end-to-end (Phase 1 of `docs/design/search-quality-eval.md`): single-system baselines on 7 query classes + 3 paired v1.1.0 → v1.2.0 version-diff audits, all checked into `docs/audits/`\n\n## License\n\nMIT License - see [LICENSE](LICENSE) for details\n\n## Acknowledgments\n\n- Built with Swift 6.3 and Swift Package Manager\n- Uses [swift-argument-parser](https://github.com/apple/swift-argument-parser) for CLI\n- Implements [Model Context Protocol](https://modelcontextprotocol.io) specification\n- Inspired by the need for offline Apple documentation access\n\n## Related Repositories\n\n- **[cupertino-docs](https://github.com/mihaelamj/cupertino-docs)** - Pre-built documentation archive for quick installation\n- **[cupertino-sample-code](https://github.com/mihaelamj/cupertino-sample-code)** - Apple sample code repository mirror\n- **[cupertino-packages](https://github.com/mihaelamj/cupertino-packages)** - Swift package source corpus indexed into `packages.db`\n- **[cupertino-symbolgraphs](https://github.com/mihaelamj/cupertino-symbolgraphs)** - Apple SDK symbol-graph corpus, the source for the `apple-constraints.json` and `apple-conformances.json` enrichment tables\n\nThe docs and sample-code repositories will be used by the planned `make install (full)` command (see [#52](https://github.com/mihaelamj/cupertino/issues/52)), providing pre-built documentation and sample code to avoid the initial 20+ hour crawl.\n\n## Support\n\n- **Issues:** [GitHub Issues](https://github.com/mihaelamj/cupertino/issues)\n- **Discussions:** [GitHub Discussions](https://github.com/mihaelamj/cupertino/discussions)\n\n---\n\n**Note:** This tool is for educational and development purposes. Respect Apple's Terms of Service when using their documentation.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmihaelamj%2Fcupertino","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmihaelamj%2Fcupertino","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmihaelamj%2Fcupertino/lists"}