# MVS Setup/Init, Skill Format, CLI Surface, and Migration Research

**Date**: 2026-03-09
**Scope**: mcp-vector-search codebase — setup/init internals, Claude Code skill format, full CLI/MCP tool surface, migration system

---

## 1. What `mvs setup` / `mvs init` Does and Where It Writes Files

### Two commands, different philosophies

There are two separate commands:

| Command | File | Style |
|---|---|---|
| `mvs setup` | `cli/commands/setup.py` | Zero-config, auto-detects everything, 8-phase pipeline |
| `mvs init` | `cli/commands/init.py` | Advanced/manual, explicit flags for each option |

`mvs setup` is the recommended entry point. `mvs init` is the lower-level primitive that `setup` internally delegates to via `ProjectManager.initialize()`.

---

### `mvs setup` — 8-phase pipeline

**Source**: `setup.py:_run_smart_setup()` (called by `main()` callback at line 850)

**Phase 1 — Detection**
- Auto-detects project root (walks up looking for `.git`, `pyproject.toml`, `package.json`, etc.)
- Runs `detect_languages()` on the project
- Scans file extensions with a 5-second timeout (`scan_project_file_extensions`)
- Detects installed MCP platforms via `detect_all_platforms()` from `py_mcp_installer`
- Excludes `Platform.CLAUDE_DESKTOP` from auto-configuration

**Phase 2 — Configuration**
- Chooses file extensions (detected or `DEFAULT_FILE_EXTENSIONS`)
- Selects embedding model via `select_optimal_embedding_model(languages)`
- Hardcodes `similarity_threshold = 0.5`

**Phase 3 — Initialization**
- Calls `ProjectManager.initialize()` — creates the `.mcp-vector-search/` directory tree and writes `config.json`
- Skipped if project is already initialized and `--force` not passed

**Phase 4 — Indexing**
- Runs `run_indexing()` from `index.py` (chunk + embed + KG build)
- Only runs on first setup or when `--force` is passed; subsequent `mvs setup` runs skip indexing

**Phase 5 — MCP Integration**
- Calls `_install_to_platform()` for each detected platform (from `py_mcp_installer`)
- If Claude CLI is available, uses `claude mcp add --transport stdio mcp-vector-search -- mcp-vector-search mcp`
- Creates `.mcp.json` in the project root (written by the `claude mcp add --scope=project` flow)

**Phase 6 — LLM API Key Setup**
- Interactive prompt for OpenRouter/OpenAI key
- Saves key to `.mcp-vector-search/` config (not the project root)

**Phase 7 — Skills Installation** (THE HOOK OF INTEREST)
- Calls `get_available_skills()` from `src/mcp_vector_search/skills/__init__.py`
- Tries these directories in order:
  1. `~/.config/claude/skills/`
  2. `~/.claude/skills/`
  3. `~/AppData/Roaming/Claude/skills/` (Windows)
- For each skill, calls `install_skill_to_claude(skill_name, claude_dir)` which creates:
  - `{claude_dir}/{skill_name}/SKILL.md`
- This phase is non-blocking — failures print a warning and continue

**Phase 8 — Completion summary and next-steps panel**

---

### Files written by `mvs setup` / `mvs init`

```
{project_root}/
  .mcp-vector-search/               # created by ProjectManager.initialize()
    config.json                     # project config (extensions, model, threshold, paths)
    schema_version.json             # schema version written by save_schema_version()
    lance/                          # LanceDB tables (chunks.lance, vectors, etc.)
  .mcp.json                         # Claude Code MCP server entry (written by claude mcp add --scope=project)
  .gitignore                        # .mcp-vector-search/ entry added automatically

~/.claude/skills/                   # OR ~/.config/claude/skills/
  {skill_name}/
    SKILL.md                        # skill content
```

**`ProjectManager.initialize()` detail** (`core/project.py:81-184`):
- Creates `{project_root}/.mcp-vector-search/` (the index path)
- Saves `config.json` at `{project_root}/.mcp-vector-search/config.json`
- Adds `.mcp-vector-search/` to `.gitignore`
- On `--force`: backs up old `config.json` to `config.json.bak`, then `shutil.rmtree` the index dir

**`save_schema_version()`** writes `{project_root}/.mcp-vector-search/schema_version.json` immediately after `initialize()` in `init.py`.

---

## 2. Claude Code Skill Format

### The `.claude/skills/` structure in THIS project

This project already has an extensive `.claude/skills/` tree. Each skill lives at:

```
.claude/skills/{skill-name}/SKILL.md
.claude/skills/{skill-name}/references/   # optional supporting docs
.claude/skills/{skill-name}/metadata.json # optional (some skills use this instead)
```

**Examples found**:
- `.claude/skills/toolchains-python-validation-pydantic/SKILL.md`
- `.claude/skills/universal-collaboration-dispatching-parallel-agents/SKILL.md`
- `.claude/skills/universal-debugging-systematic-debugging/references/*.md`

### SKILL.md format (from `toolchains-python-validation-pydantic/SKILL.md`)

```markdown
---
name: pydantic
description: Python data validation using type hints ...
progressive_disclosure:
  entry_point:
    - summary
    - when_to_use
    - quick_start
  full_content: all
token_estimates:
  entry_point: 70
  full: 5500
---

# Pydantic Validation Skill

## Summary
...

## When to Use
...

## Quick Start
...

---

## Core Concepts
...
```

Key elements of the format:
- **YAML frontmatter** with `name`, `description`, `progressive_disclosure`, `token_estimates`
- `progressive_disclosure.entry_point` lists sections loaded first (lightweight context)
- `progressive_disclosure.full_content: all` means full file on demand
- `token_estimates` gives budget hints to the model
- Body is standard markdown with `## Summary`, `## When to Use`, `## Quick Start` as the standard entry-point sections

### The skill bundle SHIPPED inside MVS

`src/mcp_vector_search/skills/mcp-vector-search-pr-mr-skill.md` — a single flat markdown file (no frontmatter), used as the PR/MR review skill. The `skills/__init__.py` reads `.md` files from the package directory and writes them as:

```
{claude_dir}/{skill_name}/SKILL.md
```

The metadata parser in `get_skill_metadata()` looks for:
- `# Title` — first `# ` line → `metadata["title"]`
- `**Version**: ...` line → `metadata["version"]`
- `**Compatible**: ...` → `metadata["compatible"]`
- `**Author**: ...` → `metadata["author"]`

So the simpler skill format (no frontmatter) uses `**Key**: Value` lines at the bottom for metadata.

---

## 3. Full CLI Command List

From `mvs --help`:

| Command | Alias | Description |
|---|---|---|
| `setup` | — | Zero-config smart setup (recommended) |
| `init` | — | Initialize project for semantic search (advanced) |
| `install` | — | Install project and MCP integrations |
| `uninstall` | `remove` | Remove MCP integrations |
| `search` | — | Semantic code search |
| `chat` | `ask` | LLM Q&A about your code |
| `index` | — | Index codebase (chunk + embed + KG) |
| `reindex` | — | DEPRECATED — use `index` |
| `embed` | — | DEPRECATED — use `index embed` |
| `index-code` | — | Code-specific embeddings (CodeT5+) |
| `progress` | — | Show indexing progress |
| `profile` | — | Profile codebase characteristics |
| `status` | — | Show project status and statistics |
| `doctor` | — | Check system dependencies |
| `help` | — | Contextual help |
| `version` | `-v` | Show version information |
| `demo` | — | Interactive demo with sample project |
| `mcp` | — | MCP server operations |
| `config` | — | Manage project configuration |
| `skills` | — | Manage and install MCP Vector Search skills |
| `reset` | — | Reset and recovery operations |
| `migrate` | — | Database migration operations |
| `vendor-patterns` | — | Manage vendor ignore patterns |
| `analyze` | — | Code complexity and quality analysis |
| `visualize` | — | Interactive code graph |
| `wiki` | — | Generate wiki/ontology of codebase concepts |
| `kg` | — | Knowledge graph operations |
| `story` | — | Generate development narrative from git history |

**`mvs skills` subcommands**: `list`, `show`, `install`, `install-all`, `uninstall`

**`mvs init` subcommands**: `check`, `mcp`, `models`

**`mvs migrate` subcommands**: `list`, `migrate` (default), `status`, `db`

---

## 4. Full MCP Tool List

Registered in `src/mcp_vector_search/mcp/tool_schemas.py` via `get_tool_schemas()`:

| Tool Name | Purpose |
|---|---|
| `search_code` | Natural language → code search |
| `search_similar` | Find code similar to a given snippet |
| `search_context` | Search with surrounding context |
| `get_project_status` | Project indexing statistics |
| `index_project` | Trigger indexing from MCP |
| `embed_chunks` | Embed specific code chunks |
| `analyze_project` | Complexity and quality analysis |
| `analyze_file` | Analyze a specific file |
| `find_smells` | Code smell detection |
| `get_complexity_hotspots` | Find high-complexity areas |
| `check_circular_dependencies` | Circular import/dep detection |
| `interpret_analysis` | LLM-powered analysis interpretation |
| `save_report` | Save analysis report to file |
| `review_repository` | Full repository code review |
| `review_pull_request` | PR diff review |
| `code_review` | General code review |
| `wiki_generate` | Generate codebase wiki/ontology |
| `kg_build` | Build knowledge graph |
| `kg_stats` | Knowledge graph statistics |
| `kg_query` | Query knowledge graph entities |
| `kg_ontology` | KG ontology/schema exploration |
| `kg_ia` | KG impact analysis |
| `trace_execution_flow` | N-hop execution flow tracing |
| `kg_history` | KG commit/history queries |
| `kg_callers_at_commit` | Who called a function at a commit |
| `story_generate` | Generate development narrative |

**Total: 26 MCP tools**

---

## 5. Where a Post-Setup Hook Should Go to Install a Skill

### Current hook location

Phase 7 of `_run_smart_setup()` in `setup.py` (lines 1132-1180) is the existing, live post-setup hook for skill installation. This is the correct and already-wired location.

The hook:
1. Discovers skills via `get_available_skills()` (reads `.md` files from `src/mcp_vector_search/skills/`)
2. Auto-detects the Claude skills directory
3. Calls `install_skill_to_claude(skill_name, claude_dir)` → creates `{claude_dir}/{skill_name}/SKILL.md`
4. Is non-blocking (failures are warnings, not errors)

### To add a new skill to the bundle

Drop a `.md` file into `src/mcp_vector_search/skills/`. The `get_available_skills()` function discovers them automatically by globbing `*.md` in that package directory. The file will be installed to `~/.claude/skills/{skill_name}/SKILL.md` on the next `mvs setup` run.

### To add a project-local skill (alternative path)

The `.claude/skills/{name}/SKILL.md` in the project root is also read by Claude Code at startup for project-scoped skills. Skill installation could write there instead of (or in addition to) `~/.claude/skills/`.

### Idempotency note

`install_skill_to_claude()` in `skills/__init__.py` unconditionally overwrites — it does `skill_dir.mkdir(parents=True, exist_ok=True)` then writes the file. The CLI `install` command has `--force` guard logic, but the low-level function does not check for existing content. This means each `mvs setup` run reinstalls all skills (safe but slightly wasteful).

---

## 6. Versioning and Migration Pattern

### Schema versioning — `core/schema.py`

A **separate** schema version (currently `"2.4.0"`) is tracked independently of the package version. It only bumps when LanceDB table fields change (added/removed columns).

```
.mcp-vector-search/schema_version.json
  {
    "version": "2.4.0",
    "updated_at": "<ISO timestamp>"
  }
```

The `SCHEMA_CHANGELOG` dict documents when each schema version was introduced. `check_schema_compatibility()` does an exact-match version check (major.minor.patch must all match). On mismatch, the database is flagged for reset (no in-place migration — LanceDB Arrow schemas are immutable, so column addition requires full table recreation).

`save_schema_version()` is called at the end of `init.py`'s `main()` after `initialize()` succeeds, and also during `migrate_schema()`.

### Migration system — `cli/commands/migrate.py` + `migrations/`

A dedicated `MigrationRunner` class with registered migrations:

| Migration | Version |
|---|---|
| `CodeXEmbedMigration` | `1.2.2` |
| `TwoPhaseArchitectureMigration` | `2.3.0` |

Migrations are:
- Registered in `_get_runner()` — new migrations added to the list there
- Tracked by execution status (success/failed/skipped/pending) stored in a registry
- Run with `mvs migrate` (or auto-detected pending migrations)
- Support `--dry-run`, `--force`, `--version` flags
- Semantic version ordered

The migration registry stores execution history separately from `schema_version.json`. The two systems are parallel: `schema_version.json` is for database field compatibility checks; the migration registry is for discrete data transformation steps.

### `reindex.py` — no upgrade logic

`reindex.py` (deprecated in favor of `mvs index`) contains no upgrade/migration logic. It only runs the chunk→embed→KG pipeline. Migration is handled entirely by the separate `migrate` command.

### Summary of version-tracking files

| File | Purpose |
|---|---|
| `.mcp-vector-search/config.json` | Project config (model, extensions, paths) |
| `.mcp-vector-search/schema_version.json` | DB schema compatibility stamp |
| `.mcp-vector-search/lance/` | LanceDB tables (chunks, vectors, KG) |
| `.mcp.json` | Claude Code MCP server registration (project-scoped) |
| `~/.claude/skills/{name}/SKILL.md` | Installed Claude Code skills |

---

## Key Findings Summary

1. **`mvs setup` is an 8-phase pipeline** in `setup.py:_run_smart_setup()`. It auto-detects everything and is designed to be idempotent (safe to re-run; only re-indexes on first run or `--force`).

2. **`mvs init` is the lower-level primitive** with explicit flags. It calls `ProjectManager.initialize()` then `save_schema_version()`.

3. **Phase 7 of `mvs setup` is the existing post-setup skill installation hook**. It already installs skills from `src/mcp_vector_search/skills/*.md` to `~/.claude/skills/{name}/SKILL.md`. To add a new skill to auto-install: drop a `.md` file into `src/mcp_vector_search/skills/`.

4. **Skill format** (SKILL.md): either (a) YAML frontmatter with `name/description/progressive_disclosure/token_estimates` + markdown body, or (b) plain markdown with `**Version**:` / `**Author**:` metadata lines at the bottom. The installed file is always named `SKILL.md` inside a directory named after the skill.

5. **Migration system is mature**: separate `MigrationRunner` with versioned migrations, schema compatibility checks via `schema_version.json`, and `mvs migrate` CLI. LanceDB schema changes require full table recreation (no ALTER TABLE equivalent).

6. **No write to `.claude/`** during setup/init. Skills go to `~/.claude/skills/` (global) not `.claude/skills/` (project-local). MCP config goes to `.mcp.json` (project root, via `claude mcp add --scope=project`).
