feat: Xcode 26.3 integration — install script, updated docs, blog post

Discovered that Xcode's claudeai-mcp feature gate blocks custom MCP
servers from the global .claude config. Project-level .mcp.json files
bypass this gate entirely — this is now the documented method.

- Add scripts/xcode-setup.sh: auto-installs vestige-mcp and configures
  .mcp.json for any Xcode project with checksum verification
- Rewrite docs/integrations/xcode.md with .mcp.json method, gate bypass
  docs, and new troubleshooting for "Agent has been closed" error
- Add docs/blog/xcode-memory.md: launch blog post for Vestige on Xcode
This commit is contained in:
Sam Valladares 2026-02-20 17:33:23 -06:00
parent 1bc4a762dc
commit 33d8b6b405
3 changed files with 527 additions and 110 deletions

148
docs/blog/xcode-memory.md Normal file
View file

@ -0,0 +1,148 @@
# I Gave Xcode's AI Agent a Memory. It Remembered My Deadlines.
*Xcode 26.3's AI coding assistant forgets everything between sessions. I fixed that in 30 seconds with one file.*
---
Xcode 26.3 shipped with something big: native support for AI coding agents. Claude and Codex can now read your project, run builds, write code, and iterate on fixes — all inside Xcode.
But there's a problem nobody's talking about: **it forgets everything.**
Every time you start a new session, the agent has zero context. Your architecture decisions? Gone. That bug you spent an hour debugging yesterday? Gone. Your coding conventions, project patterns, library preferences? All gone. You start from scratch every single time.
I fixed this with one file and 30 seconds.
## The Setup
[Vestige](https://github.com/samvallad33/vestige) is a cognitive memory system built on 130 years of memory research. It uses FSRS-6 spaced repetition (the algorithm behind modern Anki), prediction error gating, synaptic tagging, and spreading activation — all running in a single Rust binary, 100% local.
It speaks MCP (Model Context Protocol), the same protocol Xcode 26.3 uses for tool integration. So connecting them was trivial.
**Step 1:** Install Vestige
```bash
curl -L https://github.com/samvallad33/vestige/releases/latest/download/vestige-mcp-aarch64-apple-darwin.tar.gz | tar -xz
sudo mv vestige-mcp vestige vestige-restore /usr/local/bin/
```
**Step 2:** Drop one file in your project root
```bash
cat > .mcp.json << 'EOF'
{
"mcpServers": {
"vestige": {
"type": "stdio",
"command": "/usr/local/bin/vestige-mcp",
"args": [],
"env": {
"PATH": "/usr/local/bin:/usr/bin:/bin"
}
}
}
}
EOF
```
**Step 3:** Restart Xcode.
That's it. Type `/context` in the Agent panel and you'll see 23 Vestige tools loaded alongside Xcode's built-in tools.
## What Happened Next
I told the agent: *"Remember that SoulVault is the first offline-first journaling app with enhanced encryption and emotional AI, launching in 2026."*
It responded:
> Remembering...
Then it searched Vestige for existing context (`mcp__vestige__search`), checked my intentions (`mcp__vestige__intention`), and since it didn't find SoulVault context yet, it saved the information (`mcp__vestige__smart_ingest`).
Then — without me asking — it surfaced my pending reminders. Product launch deadlines, hackathon dates, even personal events. All pulled from Vestige's memory, displayed right inside Xcode's Agent panel.
My AI coding assistant just pulled my deadlines. Inside my IDE. While I was coding.
## It Gets Better: Self-Correcting Memory
Then I tested something. I asked the agent about a detail I suspected was wrong — a cat named "Whiskers" that had been hallucinated by a previous integration.
The agent:
1. Searched Vestige — didn't find "Whiskers"
2. Searched deeper — found a memory about *planning* to get a cat
3. Traced the hallucination to a specific memory ID from an older integration
4. **Deleted the bad memory on its own**
5. Corrected the record: *"you're planning to get a cat — you don't currently have one"*
The AI debugging its own memory, autonomously, inside Xcode. No other memory system does this — the flat JSON knowledge graphs would just keep the wrong data forever.
## Why This Matters
Every other MCP "memory server" is a JSON file with `create_entity` and `create_relation`. They "remember" the way a notepad remembers — they store text. There's no decay, no consolidation, no deduplication, no self-correction.
Vestige remembers the way a brain does:
- **FSRS-6 spaced repetition** — memories naturally decay and strengthen based on usage, trained on 700M+ reviews
- **Prediction error gating** — automatically deduplicates and decides whether to create, update, or supersede memories
- **Spreading activation** — searching for one memory strengthens related memories
- **Synaptic tagging** — important memories get tagged for long-term consolidation
- **23 cognitive tools** — search, ingest, dream, predict, explore connections, garbage collect, and more
All running locally in a single Rust binary. No cloud. No API keys. No data leaves your machine.
## The Technical Gotcha
Here's something I discovered that isn't documented anywhere: Xcode 26.3's Claude Agent may not load custom MCP servers configured in the global config file at `~/Library/Developer/Xcode/CodingAssistant/ClaudeAgentConfig/.claude`. There's an internal feature gate that can block them.
**The solution:** Use a project-level `.mcp.json` file instead. Xcode's agent reliably loads MCP servers from project-root `.mcp.json` files. That's why the setup above uses `.mcp.json` in the project root rather than the global Claude config.
## One More Thing
If Xcode's agent ever gives you "Prompt stream failed: Agent has been closed" — that's usually a corrupted config directory. The nuclear fix:
```bash
mv ~/Library/Developer/Xcode/CodingAssistant/ClaudeAgentConfig \
~/Library/Developer/Xcode/CodingAssistant/ClaudeAgentConfig.bak
```
Restart Xcode, sign back in, re-add your `.mcp.json`. Fresh start.
## Try It
The full setup takes 30 seconds:
```bash
# Install Vestige
curl -L https://github.com/samvallad33/vestige/releases/latest/download/vestige-mcp-aarch64-apple-darwin.tar.gz | tar -xz
sudo mv vestige-mcp vestige vestige-restore /usr/local/bin/
# Add to your project (run from project root)
cat > .mcp.json << 'EOF'
{
"mcpServers": {
"vestige": {
"type": "stdio",
"command": "/usr/local/bin/vestige-mcp",
"args": [],
"env": {
"PATH": "/usr/local/bin:/usr/bin:/bin"
}
}
}
}
EOF
# Restart Xcode. Done.
```
Or use the one-liner setup script:
```bash
curl -sSL https://raw.githubusercontent.com/samvallad33/vestige/main/scripts/xcode-setup.sh -o xcode-setup.sh
bash xcode-setup.sh
```
**Your AI coding assistant forgets everything between sessions. Give it a brain.**
[GitHub](https://github.com/samvallad33/vestige) | [Full Xcode Guide](https://github.com/samvallad33/vestige/blob/main/docs/integrations/xcode.md)
---
*Vestige is open source (AGPL-3.0). 100% local. No cloud. No API keys. Your memories never leave your machine.*

View file

@ -1,6 +1,6 @@
# Xcode 26.3
> Give Apple Intelligence a brain that remembers.
> Give Xcode's AI agent a brain that remembers.
Xcode 26.3 supports [agentic coding](https://developer.apple.com/documentation/xcode/giving-agentic-coding-tools-access-to-xcode) with full MCP (Model Context Protocol) integration. Vestige plugs directly into Xcode's Claude Agent, giving it persistent memory across every coding session.
@ -8,116 +8,60 @@ Xcode 26.3 supports [agentic coding](https://developer.apple.com/documentation/x
---
## Prerequisites
## Quick Start (30 seconds)
- **Xcode 26.3** or later (Release Candidate or stable)
- **vestige-mcp** binary installed ([Installation guide](../../README.md#quick-start))
Verify Vestige is installed:
### 1. Install Vestige
```bash
which vestige-mcp
# Should output: /usr/local/bin/vestige-mcp
curl -L https://github.com/samvallad33/vestige/releases/latest/download/vestige-mcp-aarch64-apple-darwin.tar.gz | tar -xz
sudo mv vestige-mcp vestige vestige-restore /usr/local/bin/
```
If you installed to a different location, note the **absolute path** — you'll need it below.
### 2. Add to your Xcode project
---
## Setup
### 1. Open the config file
Xcode's Claude Agent reads MCP configuration from:
```
~/Library/Developer/Xcode/CodingAssistant/ClaudeAgentConfig/.claude
```
Create or edit this file:
Create a `.mcp.json` file in your project root:
```bash
mkdir -p ~/Library/Developer/Xcode/CodingAssistant/ClaudeAgentConfig
open -e ~/Library/Developer/Xcode/CodingAssistant/ClaudeAgentConfig/.claude
```
### 2. Add Vestige
Paste the following configuration:
```json
cat > /path/to/your/project/.mcp.json << 'EOF'
{
"projects": {
"*": {
"mcpServers": {
"vestige": {
"type": "stdio",
"command": "/usr/local/bin/vestige-mcp",
"args": [],
"env": {
"PATH": "/usr/local/bin:/usr/bin:/bin"
}
}
},
"hasTrustDialogAccepted": true
"mcpServers": {
"vestige": {
"type": "stdio",
"command": "/usr/local/bin/vestige-mcp",
"args": [],
"env": {
"PATH": "/usr/local/bin:/usr/bin:/bin"
}
}
}
}
EOF
```
> **Important:** Xcode runs agents in a sandboxed environment that does **not** inherit your shell configuration (`.zshrc`, `.bashrc`, etc.). You **must** use absolute paths for the `command` field and explicitly set `PATH` in the `env` block.
Or use the setup script:
#### Project-specific memory
To give each project its own isolated memory, use `--data-dir`:
```json
{
"projects": {
"/Users/you/Developer/MyApp": {
"mcpServers": {
"vestige": {
"type": "stdio",
"command": "/usr/local/bin/vestige-mcp",
"args": ["--data-dir", "/Users/you/Developer/MyApp/.vestige"],
"env": {
"PATH": "/usr/local/bin:/usr/bin:/bin"
}
}
},
"hasTrustDialogAccepted": true
}
}
}
```bash
curl -sSL https://raw.githubusercontent.com/samvallad33/vestige/main/scripts/xcode-setup.sh -o xcode-setup.sh
bash xcode-setup.sh
```
### 3. Restart Xcode
Quit and reopen Xcode. The Claude Agent will now load Vestige on startup.
Quit Xcode completely (Cmd+Q) and reopen your project.
### 4. Verify
In Xcode's Agent panel, type:
```
/context
```
You should see `vestige` listed as an available MCP server with its tools (search, smart_ingest, memory, etc.).
Type `/context` in the Agent panel. You should see `vestige` listed with 23 tools.
---
## First Use
## Why `.mcp.json` instead of the global config?
Open any project and ask the Claude Agent:
Xcode 26.3's Claude Agent has a feature gate (`claudeai-mcp`) that blocks custom MCP servers configured in the global config at `~/Library/Developer/Xcode/CodingAssistant/ClaudeAgentConfig/.claude`.
> "Remember that this project uses SwiftUI with MVVM architecture and targets iOS 18+"
**Project-level `.mcp.json` files bypass this gate entirely.** This is the method that actually works. Drop the file in your project root and Xcode loads it on the next session.
Start a **new session**, then ask:
> "What architecture does this project use?"
It remembers.
> **Important:** Xcode runs agents in a sandboxed environment that does **not** inherit your shell configuration (`.zshrc`, `.bashrc`, etc.). You **must** use absolute paths for the `command` field.
---
@ -129,6 +73,7 @@ It remembers.
| Re-explain SwiftUI conventions each time | Agent knows your conventions from day one |
| Bug fixes are forgotten | Agent remembers past fixes and avoids regressions |
| No context between Xcode and other IDEs | Shared memory across Xcode, Cursor, VS Code, and more |
| AI hallucinations persist forever | Agent detects and self-corrects bad memories |
### Example Workflows
@ -138,11 +83,67 @@ It remembers.
**Bug documentation:**
> The agent fixes a Core Data migration crash? Vestige automatically stores the fix. Next time it encounters a migration issue, it remembers the solution.
**Proactive reminders:**
> The agent surfaces your pending deadlines, hackathon dates, and concert tickets — right inside Xcode's Agent panel.
**Self-correcting memory:**
> The agent traces a hallucinated detail back to a specific memory, identifies it as wrong, and deletes it autonomously.
**Cross-IDE memory:**
> Fix a backend bug in VS Code. Open the iOS app in Xcode. The agent already knows about the API change because Vestige shares memory across all your tools.
---
## Add Vestige to Every Project
Run the setup script with `a` to install into all detected projects:
```bash
curl -sSL https://raw.githubusercontent.com/samvallad33/vestige/main/scripts/xcode-setup.sh -o xcode-setup.sh
bash xcode-setup.sh
```
Or manually drop `.mcp.json` into any project:
```bash
# From inside your project directory
cat > .mcp.json << 'EOF'
{
"mcpServers": {
"vestige": {
"type": "stdio",
"command": "/usr/local/bin/vestige-mcp",
"args": [],
"env": {
"PATH": "/usr/local/bin:/usr/bin:/bin"
}
}
}
}
EOF
```
### Per-project isolated memory
To give each project its own memory database:
```json
{
"mcpServers": {
"vestige": {
"type": "stdio",
"command": "/usr/local/bin/vestige-mcp",
"args": ["--data-dir", "/Users/you/Developer/MyApp/.vestige"],
"env": {
"PATH": "/usr/local/bin:/usr/bin:/bin"
}
}
}
}
```
---
## Tips
### Use a CLAUDE.md for proactive memory
@ -162,23 +163,13 @@ See [CLAUDE.md templates](../CLAUDE-SETUP.md) for a full setup.
### Embedding model cache
The first time Vestige runs, it downloads the Nomic embedding model (~130MB). In Xcode's sandboxed environment, the cache location is:
The first time Vestige runs, it downloads the embedding model (~130MB). In Xcode's sandboxed environment, the cache location is:
```
~/Library/Caches/com.vestige.core/fastembed
```
If the download fails behind a corporate proxy, pre-download by running `vestige-mcp` once from your terminal before using it in Xcode.
### Skills integration
You can add Vestige-related skills to Xcode's skills directory:
```
~/Library/Developer/Xcode/CodingAssistant/ClaudeAgentConfig/skills/
```
Drop a markdown file describing how the agent should use memory for your iOS/macOS projects.
If the download fails behind a corporate proxy, pre-download by running `vestige-mcp` once from your terminal.
---
@ -187,39 +178,51 @@ Drop a markdown file describing how the agent should use memory for your iOS/mac
<details>
<summary>"vestige" not showing in /context</summary>
1. Verify the binary path is correct and absolute:
1. Make sure `.mcp.json` is in your **project root** (same directory as `.xcodeproj` or `Package.swift`):
```bash
ls -la /path/to/project/.mcp.json
```
2. Verify the binary path is correct and absolute:
```bash
ls -la /usr/local/bin/vestige-mcp
```
2. Check that the config file is valid JSON:
3. Check that `.mcp.json` is valid JSON:
```bash
cat ~/Library/Developer/Xcode/CodingAssistant/ClaudeAgentConfig/.claude | python3 -m json.tool
cat /path/to/project/.mcp.json | python3 -m json.tool
```
3. Ensure you fully quit and restarted Xcode (Cmd+Q, not just close window).
4. Fully quit and restart Xcode (Cmd+Q, not just close window).
4. Check Xcode's agent logs for errors:
5. Check debug logs:
```bash
log show --predicate 'subsystem == "com.apple.dt.Xcode"' --last 5m | grep -i mcp
cat ~/Library/Developer/Xcode/CodingAssistant/ClaudeAgentConfig/debug/latest | grep -i vestige
```
</details>
<details>
<summary>Agent can't find vestige-mcp binary</summary>
<summary>"Agent has been closed" or "Your request couldn't be completed"</summary>
Xcode's sandbox does not inherit your shell PATH. Use the full absolute path:
This is a known issue with Xcode 26.3's Claude Agent that can happen independently of MCP configuration.
```json
"command": "/usr/local/bin/vestige-mcp"
**Nuclear fix:** Delete the agent config and let Xcode recreate it:
```bash
mv ~/Library/Developer/Xcode/CodingAssistant/ClaudeAgentConfig \
~/Library/Developer/Xcode/CodingAssistant/ClaudeAgentConfig.bak
```
Then restart Xcode and sign back into Claude in Settings > Intelligence.
If you installed via `cargo build`, the binary is likely at:
```
/Users/you/.cargo/bin/vestige-mcp
```
</details>
<details>
<summary>Global .claude config not loading MCP servers</summary>
Xcode 26.3 has a feature gate (`claudeai-mcp`) that may block custom MCP servers from the global config file at `~/Library/Developer/Xcode/CodingAssistant/ClaudeAgentConfig/.claude`.
**Solution:** Use project-level `.mcp.json` instead. This bypasses the gate. See the [Quick Start](#quick-start-30-seconds) above.
Or wherever you copied it. Run `which vestige-mcp` in your terminal to find it.
</details>
<details>
@ -234,6 +237,7 @@ Behind a proxy:
```bash
HTTPS_PROXY=your-proxy:port vestige-mcp
```
</details>
---

265
scripts/xcode-setup.sh Executable file
View file

@ -0,0 +1,265 @@
#!/usr/bin/env bash
set -euo pipefail
# Vestige Xcode Setup
# Gives Xcode's AI agent persistent memory in 30 seconds.
# https://github.com/samvallad33/vestige
VESTIGE_VERSION="latest"
BINARY_NAME="vestige-mcp"
MCP_CONFIG='.mcp.json'
# Colors
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
BOLD='\033[1m'
NC='\033[0m'
print_step() { echo -e "\n${BLUE}${NC} ${BOLD}$1${NC}"; }
print_ok() { echo -e " ${GREEN}${NC} $1"; }
print_warn() { echo -e " ${YELLOW}!${NC} $1"; }
print_err() { echo -e " ${RED}${NC} $1"; }
echo -e "${BOLD}"
echo " ╦ ╦┌─┐┌─┐┌┬┐┬┌─┐┌─┐"
echo " ╚╗╔╝├┤ └─┐ │ ││ ┬├┤ "
echo " ╚╝ └─┘└─┘ ┴ ┴└─┘└─┘"
echo -e "${NC}"
echo " Memory for Xcode's AI Agent"
echo ""
# --- Step 1: Detect or install vestige-mcp ---
print_step "Checking for vestige-mcp..."
VESTIGE_PATH=""
for p in /usr/local/bin/vestige-mcp "$HOME/.local/bin/vestige-mcp" "$HOME/.cargo/bin/vestige-mcp"; do
if [ -x "$p" ]; then
VESTIGE_PATH="$p"
break
fi
done
if [ -n "$VESTIGE_PATH" ]; then
VERSION=$("$VESTIGE_PATH" --version 2>/dev/null || echo "unknown")
print_ok "Found: $VESTIGE_PATH ($VERSION)"
else
print_warn "vestige-mcp not found. Installing..."
ARCH=$(uname -m)
OS=$(uname -s)
if [ "$OS" = "Darwin" ] && [ "$ARCH" = "arm64" ]; then
TARBALL="vestige-mcp-aarch64-apple-darwin.tar.gz"
elif [ "$OS" = "Darwin" ] && [ "$ARCH" = "x86_64" ]; then
TARBALL="vestige-mcp-x86_64-apple-darwin.tar.gz"
elif [ "$OS" = "Linux" ] && [ "$ARCH" = "x86_64" ]; then
TARBALL="vestige-mcp-x86_64-unknown-linux-gnu.tar.gz"
else
print_err "Unsupported platform: $OS/$ARCH"
echo " Install manually: https://github.com/samvallad33/vestige#install"
exit 1
fi
URL="https://github.com/samvallad33/vestige/releases/latest/download/$TARBALL"
CHECKSUM_URL="${URL}.sha256"
VESTIGE_TMPDIR=$(mktemp -d)
trap 'rm -rf "$VESTIGE_TMPDIR"' EXIT
echo " Downloading $TARBALL..."
curl -fsSL "$URL" -o "$VESTIGE_TMPDIR/$TARBALL"
# Verify checksum if available
if curl -fsSL "$CHECKSUM_URL" -o "$VESTIGE_TMPDIR/$TARBALL.sha256" 2>/dev/null; then
echo " Verifying checksum..."
(cd "$VESTIGE_TMPDIR" && shasum -a 256 -c "$TARBALL.sha256")
print_ok "Checksum verified"
else
print_warn "No checksum file found — skipping verification"
fi
# Extract and verify binary
tar -xz -f "$VESTIGE_TMPDIR/$TARBALL" -C "$VESTIGE_TMPDIR"
if [ ! -f "$VESTIGE_TMPDIR/vestige-mcp" ] || [ ! -s "$VESTIGE_TMPDIR/vestige-mcp" ]; then
print_err "Download appears corrupt — vestige-mcp not found in tarball"
exit 1
fi
if ! file "$VESTIGE_TMPDIR/vestige-mcp" | grep -q "Mach-O\|ELF"; then
print_err "Downloaded file is not a valid binary"
exit 1
fi
chmod +x "$VESTIGE_TMPDIR/vestige-mcp"
# Prefer user-local install, fall back to /usr/local/bin with sudo
INSTALL_DIR="$HOME/.local/bin"
if [ -w "/usr/local/bin" ]; then
INSTALL_DIR="/usr/local/bin"
elif [ ! -d "$INSTALL_DIR" ]; then
mkdir -p "$INSTALL_DIR"
fi
if [ "$INSTALL_DIR" = "/usr/local/bin" ] && [ ! -w "$INSTALL_DIR" ]; then
echo ""
echo " Install location: $INSTALL_DIR (requires sudo)"
read -rp " Continue? (y/N): " confirm
if [ "$confirm" != "y" ] && [ "$confirm" != "Y" ]; then
INSTALL_DIR="$HOME/.local/bin"
mkdir -p "$INSTALL_DIR"
print_warn "Installing to $INSTALL_DIR instead"
else
sudo mv "$VESTIGE_TMPDIR/vestige-mcp" "$INSTALL_DIR/"
[ -f "$VESTIGE_TMPDIR/vestige" ] && sudo mv "$VESTIGE_TMPDIR/vestige" "$INSTALL_DIR/"
[ -f "$VESTIGE_TMPDIR/vestige-restore" ] && sudo mv "$VESTIGE_TMPDIR/vestige-restore" "$INSTALL_DIR/"
fi
fi
if [ "$INSTALL_DIR" != "/usr/local/bin" ] || [ -w "$INSTALL_DIR" ]; then
mv "$VESTIGE_TMPDIR/vestige-mcp" "$INSTALL_DIR/" 2>/dev/null || true
[ -f "$VESTIGE_TMPDIR/vestige" ] && mv "$VESTIGE_TMPDIR/vestige" "$INSTALL_DIR/" 2>/dev/null || true
[ -f "$VESTIGE_TMPDIR/vestige-restore" ] && mv "$VESTIGE_TMPDIR/vestige-restore" "$INSTALL_DIR/" 2>/dev/null || true
fi
VESTIGE_PATH="$INSTALL_DIR/vestige-mcp"
VERSION=$("$VESTIGE_PATH" --version 2>/dev/null || echo "unknown")
print_ok "Installed: $VESTIGE_PATH ($VERSION)"
fi
# --- Helper: generate .mcp.json content ---
generate_mcp_json() {
local cmd_path="$1"
# Escape backslashes and double quotes for valid JSON
local escaped_path
escaped_path=$(printf '%s' "$cmd_path" | sed 's/\\/\\\\/g; s/"/\\"/g')
cat << MCPEOF
{
"mcpServers": {
"vestige": {
"type": "stdio",
"command": "$escaped_path",
"args": [],
"env": {
"PATH": "/usr/local/bin:/usr/bin:/bin"
}
}
}
}
MCPEOF
}
# --- Step 2: Find or select project ---
print_step "Finding Xcode projects..."
PROJECT_DIR=""
if [ -n "${1:-}" ]; then
# User passed a project path
PROJECT_DIR="$(cd "$1" && pwd)"
print_ok "Using: $PROJECT_DIR"
elif ls "$(pwd)/"*.xcodeproj >/dev/null 2>&1 || [ -f "$(pwd)/Package.swift" ]; then
PROJECT_DIR="$(pwd)"
print_ok "Current directory: $PROJECT_DIR"
else
# Search for projects
PROJECTS=$(find "$HOME/Developer" -maxdepth 4 \( -name "*.xcodeproj" -o -name "Package.swift" \) 2>/dev/null | head -20)
if [ -z "$PROJECTS" ]; then
print_warn "No Xcode projects found in ~/Developer"
echo ""
echo " Usage: $0 /path/to/your/xcode/project"
echo ""
echo " Or run from inside your project directory:"
echo " cd /path/to/project && $0"
exit 1
fi
echo " Found projects:"
i=1
declare -a PROJECT_LIST=()
while IFS= read -r proj; do
dir=$(dirname "$proj")
if [ -d "$dir" ]; then
PROJECT_LIST+=("$dir")
echo " $i) $dir"
((i++))
fi
done <<< "$PROJECTS"
max_choice=$((i - 1))
echo ""
read -rp " Select project (1-$max_choice), or 'a' for all: " choice
if [ "$choice" = "a" ]; then
for dir in "${PROJECT_LIST[@]}"; do
if [ ! -f "$dir/$MCP_CONFIG" ]; then
generate_mcp_json "$VESTIGE_PATH" > "$dir/$MCP_CONFIG"
print_ok "$dir/$MCP_CONFIG"
else
print_warn "$dir/$MCP_CONFIG (already exists, skipped)"
fi
done
echo ""
echo -e "${GREEN}${BOLD}Done!${NC} Vestige added to ${#PROJECT_LIST[@]} projects."
echo ""
echo " Restart Xcode (Cmd+Q) and type /context to verify."
exit 0
elif [[ "$choice" =~ ^[0-9]+$ ]] && [ "$choice" -ge 1 ] && [ "$choice" -le "$max_choice" ]; then
idx=$((choice - 1))
PROJECT_DIR="${PROJECT_LIST[$idx]}"
print_ok "Selected: $PROJECT_DIR"
else
print_err "Invalid selection: $choice"
exit 1
fi
fi
# --- Step 3: Create .mcp.json ---
print_step "Creating $MCP_CONFIG..."
CONFIG_PATH="$PROJECT_DIR/$MCP_CONFIG"
if [ -f "$CONFIG_PATH" ]; then
print_warn "$CONFIG_PATH already exists"
read -rp " Overwrite? (y/N): " overwrite
if [ "$overwrite" != "y" ] && [ "$overwrite" != "Y" ]; then
echo " Skipped."
exit 0
fi
cp "$CONFIG_PATH" "$CONFIG_PATH.bak"
print_ok "Backed up existing config to $CONFIG_PATH.bak"
fi
generate_mcp_json "$VESTIGE_PATH" > "$CONFIG_PATH"
print_ok "Created $CONFIG_PATH"
# --- Step 4: Verify ---
print_step "Verifying vestige-mcp starts..."
if "$VESTIGE_PATH" --version >/dev/null 2>&1; then
print_ok "vestige-mcp binary OK"
else
print_err "vestige-mcp failed to start — check the binary"
exit 1
fi
# --- Done ---
echo ""
echo -e "${GREEN}${BOLD}Vestige is ready for Xcode.${NC}"
echo ""
echo " Next steps:"
echo " 1. Restart Xcode (Cmd+Q, then reopen)"
echo " 2. Open your project"
echo " 3. Type /context in the Agent panel"
echo " 4. You should see vestige listed with 23 tools"
echo ""
echo " Try it:"
echo " \"Remember that this project uses SwiftUI with MVVM architecture\""
echo " (new session) → \"What architecture does this project use?\""
echo " It remembers."
echo ""
echo -e " ${BLUE}https://github.com/samvallad33/vestige${NC}"
echo ""