diff --git a/README.md b/README.md index ab68253..997f943 100644 --- a/README.md +++ b/README.md @@ -50,6 +50,32 @@ Sample output: 2. **Index routing** – `DerivedDataPaths` ensures the path points into `Index.noindex/DataStore/IndexStoreDB` so we can open the index without extra setup. 3. **Output formatting** – Paths are normalized, deduplicated, and printed once for easier scripting. +## Agent Skill (OpenSkills) + +This repository includes an OpenSkills-compatible agent skill located in `swiftfindrefs/`. +It teaches AI coding agents to use IndexStore-based reference discovery via `swiftfindrefs` +instead of unreliable text search. + +### Install OpenSkills +```bash +npm i -g openskills +``` + +### Install this skill +```bash +openskills install michaelversus/SwiftFindRefs +``` + +### Sync into your project +```bash +openskills sync +``` + +### Example agent prompt +Use the swiftfindrefs skill to find all references to `SelectionViewController` (class) and add +`import UIComponents` only where missing. + + ## 🧪 Testing The package uses the Swift Testing framework (`swift test`) with mocks for filesystem and derived-data resolution. Tests cover locator edge cases, path building, and index error handling. diff --git a/swiftfindrefs/SKILL.md b/swiftfindrefs/SKILL.md new file mode 100644 index 0000000..20083c9 --- /dev/null +++ b/swiftfindrefs/SKILL.md @@ -0,0 +1,75 @@ +--- +name: swiftfindrefs +description: Use swiftfindrefs (IndexStoreDB) to list every Swift source file referencing a symbol. Mandatory for “find references”, “fix missing imports”, and cross-module refactors. Do not replace with grep/rg or IDE search. +--- + +# SwiftFindRefs + +## Purpose +Use `swiftfindrefs` to locate every Swift source file that references a given symbol by querying Xcode’s IndexStore (DerivedData). This skill exists to prevent incomplete refactors caused by text search or heuristics. + +## Rules +- Always run `swiftfindrefs` before editing any files. +- Only edit files returned by `swiftfindrefs`. +- Do not substitute `grep`, `rg`, IDE search, or filesystem heuristics for reference discovery. +- Do not expand the file set manually. +- If IndexStore/DerivedData resolution fails, stop and report the error. Do not guess. + +## Preconditions +- macOS with Xcode installed +- Project has been built at least once (DerivedData exists) +- `swiftfindrefs` available in PATH + +## Canonical command +Prefer providing `--projectName` and `--symbolType` when possible. + +```bash +swiftfindrefs \ + --projectName \ + --symbolName \ + --symbolType +``` + +Optional flags: +- `--derivedDataPath `: explicit DerivedData (or IndexStoreDB) path; skips discovery +- `--verbose`: prints discovery steps, resolved paths, and diagnostics + +## Output contract +- One absolute file path per line +- Deduplicated +- Script-friendly (safe to pipe line-by-line) +- Ordering is not semantically meaningful + +## Standard workflows + +### Workflow A: Find all references +1. Run `swiftfindrefs` for the symbol. +2. Treat the output as the complete reference set. +3. If more detail is needed, open only the returned files. + +### Workflow B: Fix missing imports after moving a symbol +Use `swiftfindrefs` to restrict scope, then add imports only where needed. + +```bash +swiftfindrefs -p -n -t | while read file; do + if ! grep -q "^import $" "$file"; then + echo "$file" + fi +done +``` + +Then for each printed file: +- Insert `import ` in the imports block at the top. +- Preserve existing import ordering/grouping. +- Never add duplicate imports. +- Do not reformat unrelated code. + +### Workflow C: Audit usage before deleting or renaming a symbol +1. Run `swiftfindrefs` for the symbol. +2. If output is empty, treat the symbol as unused (still validate via build/tests if needed). +3. If non-empty, review the listed files before changing public API. + +## References +- CLI details: references/cli.md +- Playbooks: references/workflows.md +- Troubleshooting: references/troubleshooting.md diff --git a/swiftfindrefs/references/cli.md b/swiftfindrefs/references/cli.md new file mode 100644 index 0000000..c230e30 --- /dev/null +++ b/swiftfindrefs/references/cli.md @@ -0,0 +1,46 @@ +# CLI reference (agent-focused) + +## Preconditions +- macOS with Xcode installed +- Project built at least once (DerivedData exists) +- `swiftfindrefs` is available in PATH + +## Flags +- `-p, --projectName` + Helps infer the correct DerivedData folder when `--derivedDataPath` is not provided. + +- `-d, --derivedDataPath` + Points directly to a DerivedData (or IndexStoreDB) directory and skips discovery. + +- `-n, --symbolName` (required) + The symbol to inspect. + +- `-t, --symbolType` + Narrows matches to a specific kind (recommended when possible). + +- `-v, --verbose` + Prints discovery steps, resolved paths, and diagnostics. + +## Recommended invocations + +Most common: +```bash +swiftfindrefs -p MyApp -n SelectionViewController -t class +``` + +Explicit DerivedData / deterministic runs: +```bash +swiftfindrefs -d ~/Library/Developer/Xcode/DerivedData/MyApp-XXXX/ -n SelectionViewController -t class +``` + +Debug discovery: +```bash +swiftfindrefs -p MyApp -n SelectionViewController -t class -v +``` + +## Output +- Absolute file paths, one per line +- Deduplicated + +## Non-goals +- The tool reports which files reference a symbol, not line or column positions. diff --git a/swiftfindrefs/references/troubleshooting.md b/swiftfindrefs/references/troubleshooting.md new file mode 100644 index 0000000..01f1331 --- /dev/null +++ b/swiftfindrefs/references/troubleshooting.md @@ -0,0 +1,18 @@ +# Troubleshooting + +## No results returned +- Build the project in Xcode to regenerate indexing. +- Re-run with verbose logging: + ```bash + swiftfindrefs -p -n -t -v + ``` +- If multiple DerivedData folders exist for the same project `swiftfindrefs` will use the most recent one. + +## Wrong DerivedData selected +- Prefer explicit `--derivedDataPath` in CI or multi-clone setups. +- Use `--verbose` to confirm path selection. + +## Do not fall back to grep +- Text search is not acceptable for reference discovery. +- grep/rg may only be used inside files already returned by `swiftfindrefs` + (for example, to check if an import already exists). diff --git a/swiftfindrefs/references/workflows.md b/swiftfindrefs/references/workflows.md new file mode 100644 index 0000000..099a302 --- /dev/null +++ b/swiftfindrefs/references/workflows.md @@ -0,0 +1,30 @@ +# Workflows (deterministic behavior) + +## Golden rule +Reference discovery must be IndexStore-based. `swiftfindrefs` output defines scope. + +## Playbook: add missing imports after moving a symbol +Inputs: +- Project: `` +- Symbol: `` +- Type: `` +- Module to import: `` + +Steps: +1. Run: + ```bash + swiftfindrefs -p -n -t + ``` +2. Iterate only over the resulting file list. +3. For each file: + - If `import ` exists: no change. + - Else: add it to the imports block at the top. +4. Keep edits minimal: + - No formatting changes + - No unrelated cleanup + - Preserve existing import ordering/grouping + +## Playbook: rename or delete a symbol +1. Run `swiftfindrefs` on the symbol. +2. If output is empty, treat as unused (validate via build/tests). +3. If non-empty, update usages only in returned files.