claude-xcindex

Hero

xcindex

Semantic Swift/ObjC symbol lookups for Claude Code, powered by Xcode’s on-disk SourceKit index.

build license: MIT Claude Code

A Claude Code plugin that lets Claude query Xcode’s existing symbol index instead of falling back to grep. References, overrides, conformances, and refactor impact analysis on Swift/ObjC code hit the same indexstore-db library SourceKit-LSP uses — USR-authoritative, sub-millisecond warm, no re-indexing.

It reads the index Xcode already writes to DerivedData during build. No daemon, no second copy of your source, no builds on your behalf. It warns when the index is stale rather than acting.

Requirements

Install

claude plugin marketplace add anthropics/claude-plugins-community
claude plugin install claude-xcindex@claude-community

First run downloads the matching xcindex binary from the GitHub release and caches it under the plugin directory — no npm install, no manual build.

Then, in a Swift project:

/xcindex-setup

This confirms the binary is ready, locates your Xcode project, and — with your confirmation — runs xcodebuild per scheme so the index is populated. Skip it if you build in Xcode yourself.

Verify with /plugin and /xcindex-status. If anything looks off, run ./bin/xcindex-doctor.

Install from a local clone Useful for pinning to a specific commit or hacking on the plugin: ```sh git clone https://github.com/drewalth/claude-xcindex.git cd claude-xcindex/service && swift build -c release ``` Then in Claude Code: ``` /plugin marketplace add /absolute/path/to/claude-xcindex /plugin install xcindex@xcindex-local ``` The launcher detects the from-source build at `service/.build/release/xcindex` and symlinks it instead of downloading.

Usage

The skills trigger automatically based on what you ask — no special syntax.

You: Find all callers of fetchUser.
Claude: [mcp__xcindex__find_symbol → mcp__xcindex__find_references]
        → 6 call sites across 4 files. Reads ±10 lines around each.
        Returns a focused summary instead of 8 full-file reads.

/xcindex-status checks index freshness and reports which files have been edited since the last build.

Tips

MCP tools

Exposed under mcp__xcindex__*. Signatures and examples in docs/tools-reference.md.

Tool Purpose
find_symbol Name → candidate USRs with kind and defining file.
find_references Every occurrence with file, line, column, role.
find_definition The canonical definition site.
find_overrides All overriding implementations of a method.
find_conformances All types conforming to a protocol.
blast_radius Minimal set of files affected by editing a file.
status Index freshness, DerivedData path, last-build timestamp.
plan_rename Semantic rename plan tiered by confidence — see docs/tools-reference.md for tier definitions, or docs/coverage.md for what each pinned fixture surfaces.

Skills & hooks

Troubleshooting

Run ./bin/xcindex-doctor — it checks Xcode, libIndexStore, the cached binary, and index freshness line-by-line with remediation hints. Full catalogue in docs/troubleshooting.md.

Development

make build-debug    # debug build
make test           # run tests (expects external fixtures checked out)
make test_ci        # run tests as CI does — skips uncheckout fixtures
make test-hooks     # bash regression tests for the hooks
make help           # list all dev targets

make test runs the external-fixture coverage suites (TCA, swift-log), which need those repos checked out under tests/fixtures/. On a fresh clone they aren’t present and the suites fail by design — a silent skip would register as a passing test with zero assertions. Either run make test_ci (sets XCINDEX_ALLOW_FIXTURE_SKIP=1 and skips them, exactly as CI does), or fetch the fixtures first: scripts/fetch-fixture.sh tca and scripts/fetch-fixture.sh swift-log.

claude-xcindex/
├── .claude-plugin/plugin.json     # plugin manifest
├── .mcp.json                      # MCP server registration
├── bin/run                        # launcher
├── service/                       # Swift MCP server
├── skills/                        # refactor-plan, find-refs, blast-radius, rename
├── agents/swift-refactor-specialist.md
├── commands/                      # /xcindex-setup, /xcindex-status
├── hooks/                         # session-start.sh, post-edit.sh, pre-grep.sh
├── scripts/                       # dev-only: build.sh, fixtures, benchmarks
└── Makefile                       # dev task runner (build, test, lint, format)

PRs welcome — see CONTRIBUTING.md. Please open an issue to discuss architectural changes first.


Why it’s faster than grep

Claude’s default answer to “where is UserService used?” is ripgrep — 40 noisy textual matches, 8 full files read to disambiguate. Expensive in tokens, imprecise in results. Xcode already solved this: every build writes a full semantic index to DerivedData, and Apple’s indexstore-db queries it. This plugin wraps those queries behind MCP tools so Claude reads only the lines that matter.

Full numbers and methodology in docs/benchmarks.md; the mental model (freshness, DerivedData resolution, USR-first lookups) in docs/how-it-works.md.

Architecture

Claude Code
    ↓ (MCP over stdio)
xcindex plugin
├── Skills          — tell Claude WHEN to use the index
├── Hooks           — freshness warnings + nudge Claude off grep on Swift code
├── Subagent        — isolated context for large renames
├── Slash commands  — /xcindex-setup, /xcindex-status
└── Swift binary    — MCP server, queries IndexStoreDB
    ↓ (reads LMDB)
DerivedData/Index.noindex/DataStore
    ↑ (writes during build)
Xcode

One native Swift binary, speaking MCP directly via Anthropic’s Swift SDK. No Node runtime, no intermediate process.

Complementary tools

This plugin focuses on semantic queries over Xcode’s on-disk index. It is not a language server and does not build, test, or run your project. Pair it with:

Anthropic’s swift-lsp

Live LSP features (completion, diagnostics, hover) backed by SourceKit-LSP. Different layer: swift-lsp is an editor-UI integration (no MCP tools the agent can call); xcindex exposes semantic queries to the agent loop. They don’t overlap.

  swift-lsp xcindex
Backend SourceKit-LSP server indexstore-db reader
Source of truth live Swift source Xcode build-time index
Requires Xcode build? No Yes (once)
Diagnostics & completion Yes No
Hover / jump-to-definition Yes Definition only
Agent-callable MCP tools No (editor-UI only) 7 tools
Overrides / conformances / blast-radius Not first-class Yes
Works on Linux / SwiftPM-only Yes No (DerivedData-specific)
Warm query latency LSP round-trip sub-millisecond
Freshness model always live hook-warned when stale

Build & test orchestration

Other Swift symbol tools

Where xcindex sits relative to the closest neighbours:

  xcindex block/xcode-index-mcp SwiftLens
Backend indexstore-db (direct) indexstore-db (direct) SourceKit-LSP
Packaging Claude Code plugin (skills + hooks + subagent) Raw MCP server Raw MCP server
Runtime Native Swift binary Python (uv) + Swift service Python 3.10+
MCP tools 7 (find_symbol, find_references, find_definition, find_overrides, find_conformances, blast_radius, status) 4 (load_index, symbol_occurrences, get_occurrences, search_pattern) 15 (single-file analysis + cross-file refs/defs)
Overrides / conformances Yes No No
Blast-radius analysis Yes No No
Freshness warnings Hook-driven, per-session None None
Status (Apr 2026) Active Active (~55⭐) Archived 2026-03-10

block/xcode-index-mcp is the closest prior art — same backend, narrower tool surface, no plugin packaging. SwiftLens covered the same niche from the SourceKit-LSP angle but was archived in March 2026.

Prior art

Privacy

Runs entirely on your local machine. No telemetry, no analytics, no tracking. The only network request is to GitHub to download the prebuilt binary on first run. All queries run locally against Xcode’s on-disk index.

License

MIT — see LICENSE.