Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ code-review-graph build # parse your codebase
One command sets up everything. `install` detects which AI coding tools you have, writes the correct MCP configuration for each one, and injects graph-aware instructions into your platform rules. It auto-detects whether you installed via `uvx` or `pip`/`pipx` and generates the right config. Restart your editor/tool after installing.

<p align="center">
<img src="diagrams/diagram8_supported_platforms.png" alt="One Install, Every Platform: auto-detects Codex, Claude Code, Cursor, Windsurf, Zed, Continue, OpenCode, Antigravity, and Kiro" width="85%" />
<img src="diagrams/diagram8_supported_platforms.png" alt="One Install, Every Platform: auto-detects Codex, Claude Code, Cursor, Windsurf, Zed, Continue, OpenCode, Antigravity, Kiro and GitHub Copilot" width="85%" />
</p>

To target a specific platform:
Expand All @@ -54,6 +54,8 @@ To target a specific platform:
code-review-graph install --platform codex # configure only Codex
code-review-graph install --platform cursor # configure only Cursor
code-review-graph install --platform claude-code # configure only Claude Code
code-review-graph install --platform copilot # GitHub Copilot in VS Code
code-review-graph install --platform copilot-cli # GitHub Copilot CLI
code-review-graph install --platform kiro # configure only Kiro
```

Expand Down Expand Up @@ -363,5 +365,5 @@ MIT. See [LICENSE](LICENSE).
<br>
<a href="https://code-review-graph.com">code-review-graph.com</a><br><br>
<code>pip install code-review-graph && code-review-graph install</code><br>
<sub>Works with Codex, Claude Code, Cursor, Windsurf, Zed, Continue, OpenCode, Antigravity, and Kiro</sub>
<sub>Works with Codex, Claude Code, Cursor, Windsurf, Zed, Continue, OpenCode, Antigravity, Kiro and GitHub Copilot</sub>
</p>
6 changes: 4 additions & 2 deletions code_review_graph/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -295,7 +295,8 @@ def main() -> None:
"--platform",
choices=[
"codex", "claude", "claude-code", "cursor", "windsurf", "zed",
"continue", "opencode", "antigravity", "qwen", "kiro", "all",
"continue", "opencode", "antigravity", "qwen", "kiro",
"copilot", "copilot-cli", "all",
],
default="all",
help="Target platform for MCP config (default: all detected)",
Expand Down Expand Up @@ -333,7 +334,8 @@ def main() -> None:
"--platform",
choices=[
"codex", "claude", "claude-code", "cursor", "windsurf", "zed",
"continue", "opencode", "antigravity", "qwen", "kiro", "all",
"continue", "opencode", "antigravity", "qwen", "kiro",
"copilot", "copilot-cli", "all",
],
default="all",
help="Target platform for MCP config (default: all detected)",
Expand Down
90 changes: 88 additions & 2 deletions code_review_graph/skills.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

import json
import logging
import os
import platform
import shutil
from pathlib import Path
Expand All @@ -19,6 +20,73 @@

# --- Multi-platform MCP install ---

def _copilot_vscode_detected() -> bool:
"""Check if the GitHub Copilot VS Code extension is installed.

Checks for the Copilot extension directory rather than just VS Code
itself, to avoid injecting config for users who have VS Code but not Copilot.
"""
extensions_dir = Path.home() / ".vscode" / "extensions"
if extensions_dir.exists():
return any(p.name.startswith("github.copilot-") for p in extensions_dir.iterdir())
return False


def _copilot_cli_detected() -> bool:
"""Check if GitHub Copilot CLI is installed."""
cli_config_primary = Path.home() / ".config" / "github-copilot"
cli_config_alt = Path.home() / ".github-copilot"
return cli_config_primary.exists() or cli_config_alt.exists()


def _vscode_user_settings_path() -> Path:
"""Return VS Code User/settings.json path for the current OS."""
system = platform.system()
if system == "Darwin":
return (
Path.home()
/ "Library"
/ "Application Support"
/ "Code"
/ "User"
/ "settings.json"
)
if system == "Windows":
appdata = os.environ.get("APPDATA")
if appdata:
return Path(appdata) / "Code" / "User" / "settings.json"
return Path.home() / "AppData" / "Roaming" / "Code" / "User" / "settings.json"
return Path.home() / ".config" / "Code" / "User" / "settings.json"


def _validate_copilot_vscode_settings(existing: Any, config_path: Path) -> bool:
"""Validate VS Code settings.json is safe to modify before writing.

VS Code's global settings.json is a critical file — a corrupt write
could break the entire editor. Only proceed if the file already exists
and contains a valid JSON object.

When ``settings.json`` is missing, this returns ``False`` and the
install is skipped. That is intentional: we do not create a brand-new
global settings file from this tool; the user should open VS Code at
least once (or create settings manually) so the file exists.
"""
if not config_path.exists():
logger.warning(
"Copilot: VS Code settings.json not found at %s; skipping to avoid "
"creating an incomplete settings file. Open VS Code first.",
config_path,
)
return False
if not isinstance(existing, dict):
logger.warning(
"Copilot: %s has unexpected structure (not a JSON object); "
"skipping to avoid corrupting VS Code settings.",
config_path,
)
return False
return True


def _zed_settings_path() -> Path:
"""Return the Zed settings.json path for the current OS."""
Expand Down Expand Up @@ -100,6 +168,20 @@ def _zed_settings_path() -> Path:
"format": "object",
"needs_type": True,
},
"copilot": {
"name": "GitHub Copilot (VS Code)",
"config_path": lambda root: _vscode_user_settings_path(),
"key": "copilot.advanced.mcpServers",
"detect": _copilot_vscode_detected,
"format": "object",
"needs_type": True,
"validate": _validate_copilot_vscode_settings,
},
"copilot-cli": {
"name": "GitHub Copilot CLI",
"config_path": lambda root: Path.home() / ".config" / "github-copilot" / "mcp_servers.json",
"key": "servers",
"detect": _copilot_cli_detected,
"kiro": {
"name": "Kiro",
"config_path": lambda root: root / ".kiro" / "settings" / "mcp.json",
Expand Down Expand Up @@ -225,15 +307,19 @@ def install_platform_configs(
configured.append(plat["name"])
continue

# Read existing config
existing: dict[str, Any] = {}
# Read existing config (may be dict, list, or other JSON value)
existing: Any = {}
if config_path.exists():
try:
existing = json.loads(config_path.read_text(encoding="utf-8"))
except (json.JSONDecodeError, OSError):
logger.warning("Invalid JSON in %s, will overwrite.", config_path)
existing = {}

# Platform-specific pre-write safety check (e.g., VS Code settings.json)
if "validate" in plat and not plat["validate"](existing, config_path):
continue

if plat["format"] == "array":
arr = existing.get(server_key, [])
if not isinstance(arr, list):
Expand Down
24 changes: 24 additions & 0 deletions docs/USAGE.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,30 @@ code-review-graph install --platform claude-code
| **Zed** | `.zed/settings.json` |
| **Continue** | `.continue/config.json` |
| **OpenCode** | `.opencode/config.json` |
| **GitHub Copilot (VS Code)** | VS Code user `settings.json` (macOS: `~/Library/Application Support/Code/User/`; Windows: `%APPDATA%\Code\User\`; Linux: `~/.config/Code/User/`) |
| **GitHub Copilot CLI** | `~/.config/github-copilot/mcp_servers.json` (also `~/.github-copilot` if present for detection) |

### GitHub Copilot Setup

If you use GitHub Copilot, configure the MCP server for your variant:

**VS Code Extension or Copilot Chat:**
```bash
code-review-graph install --platform copilot
```

**Copilot CLI:**
```bash
code-review-graph install --platform copilot-cli
```

**Both variants:**
```bash
code-review-graph install
```
The tool auto-detects both Copilot variants and installs MCP configuration for each.

For the VS Code integration, `install` updates the global user `settings.json` only if that file already exists (for example after you have opened VS Code at least once). If the file is missing, run VS Code once or create an empty `{}` in the path above, then run `install` again.

## Core Workflow

Expand Down
Loading