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
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,10 @@ code-review-graph-vscode/dist/
.claude/
.claude-plugin/

# Qoder
.qoder/
QODER.md

# Coverage
htmlcov/
.coverage
Expand Down
39 changes: 39 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -113,3 +113,42 @@ uv run code-review-graph eval # Run evaluation benchmarks
- **type-check**: mypy
- **security**: bandit scan
- **test**: pytest matrix (3.10, 3.11, 3.12, 3.13) with 50% coverage minimum

<!-- code-review-graph MCP tools -->
## MCP Tools: code-review-graph

**IMPORTANT: This project has a knowledge graph. ALWAYS use the
code-review-graph MCP tools BEFORE using Grep/Glob/Read to explore
the codebase.** The graph is faster, cheaper (fewer tokens), and gives
you structural context (callers, dependents, test coverage) that file
scanning cannot.

### When to use graph tools FIRST

- **Exploring code**: `semantic_search_nodes` or `query_graph` instead of Grep
- **Understanding impact**: `get_impact_radius` instead of manually tracing imports
- **Code review**: `detect_changes` + `get_review_context` instead of reading entire files
- **Finding relationships**: `query_graph` with callers_of/callees_of/imports_of/tests_for
- **Architecture questions**: `get_architecture_overview` + `list_communities`

Fall back to Grep/Glob/Read **only** when the graph doesn't cover what you need.

### Key Tools

| Tool | Use when |
|------|----------|
| `detect_changes` | Reviewing code changes — gives risk-scored analysis |
| `get_review_context` | Need source snippets for review — token-efficient |
| `get_impact_radius` | Understanding blast radius of a change |
| `get_affected_flows` | Finding which execution paths are impacted |
| `query_graph` | Tracing callers, callees, imports, tests, dependencies |
| `semantic_search_nodes` | Finding functions/classes by name or keyword |
| `get_architecture_overview` | Understanding high-level codebase structure |
| `refactor_tool` | Planning renames, finding dead code |

### Workflow

1. The graph auto-updates on file changes (via hooks).
2. Use `detect_changes` for code review.
3. Use `get_affected_flows` to understand impact.
4. Use `query_graph` pattern="tests_for" to check coverage.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,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, and Antigravity" 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, Qwen, and Qoder" width="85%" />
</p>

To target a specific platform:
Expand Down Expand Up @@ -331,5 +331,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, and Antigravity</sub>
<sub>Works with Codex, Claude Code, Cursor, Windsurf, Zed, Continue, OpenCode, Antigravity, Qwen, and Qoder</sub>
</p>
31 changes: 20 additions & 11 deletions code_review_graph/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,12 @@

logger = logging.getLogger(__name__)

# Shared platform choices for install and init commands
_PLATFORM_CHOICES = [
"codex", "claude", "claude-code", "cursor", "windsurf", "zed",
"continue", "opencode", "antigravity", "qwen", "qoder", "all",
]


def _get_version() -> str:
"""Get the installed package version."""
Expand Down Expand Up @@ -211,6 +217,7 @@ def _handle_init(args: argparse.Namespace) -> None:
inject_platform_instructions,
install_git_hook,
install_hooks,
install_qoder_skills,
)

if not skip_skills:
Expand All @@ -237,9 +244,17 @@ def _handle_init(args: argparse.Namespace) -> None:
elif skip_instructions:
print("Skipped instruction injection (--no-instructions).")

if not skip_hooks and target in ("claude", "all"):
install_hooks(repo_root)
print(f"Installed hooks in {repo_root / '.claude' / 'settings.json'}")

# Install Qoder skills (global user-level skills directory)
if not skip_skills and target in ("qoder", "all"):
qoder_skills_dir = install_qoder_skills(repo_root)
if qoder_skills_dir:
print(f"Installed Qoder skills to {qoder_skills_dir}")
if not skip_hooks and target in ("claude", "qoder", "all"):
platforms_to_install = [target] if target != "all" else ["claude", "qoder"]
for plat in platforms_to_install:
install_hooks(repo_root, platform=plat)
print(f"Installed hooks in {repo_root / f'.{plat}' / 'settings.json'}")
git_hook = install_git_hook(repo_root)
if git_hook:
print(f"Installed git pre-commit hook in {git_hook}")
Expand Down Expand Up @@ -293,10 +308,7 @@ def main() -> None:
help=argparse.SUPPRESS)
install_cmd.add_argument(
"--platform",
choices=[
"codex", "claude", "claude-code", "cursor", "windsurf", "zed",
"continue", "opencode", "antigravity", "qwen", "all",
],
choices=_PLATFORM_CHOICES,
default="all",
help="Target platform for MCP config (default: all detected)",
)
Expand Down Expand Up @@ -331,10 +343,7 @@ def main() -> None:
help=argparse.SUPPRESS)
init_cmd.add_argument(
"--platform",
choices=[
"codex", "claude", "claude-code", "cursor", "windsurf", "zed",
"continue", "opencode", "antigravity", "qwen", "all",
],
choices=_PLATFORM_CHOICES,
default="all",
help="Target platform for MCP config (default: all detected)",
)
Expand Down
59 changes: 56 additions & 3 deletions code_review_graph/skills.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,14 @@ def _zed_settings_path() -> Path:
"format": "object",
"needs_type": True,
},
"qoder": {
"name": "Qoder",
"config_path": lambda root: root / ".qoder" / "mcp.json",
"key": "mcpServers",
"detect": lambda: True,
"format": "object",
"needs_type": True,
},
}


Expand Down Expand Up @@ -481,16 +489,20 @@ def install_git_hook(repo_root: Path) -> Path | None:
return hook_path


def install_hooks(repo_root: Path) -> None:
"""Write hooks config to .claude/settings.json.
def install_hooks(repo_root: Path, platform: str = "claude") -> None:
"""Write hooks config to platform-specific settings.json.

Merges with existing settings if present, preserving non-hook
configuration.

Args:
repo_root: Repository root directory.
platform: Target platform ("claude" or "qoder").
"""
settings_dir = repo_root / ".claude"
if platform == "qoder":
settings_dir = repo_root / ".qoder"
else:
settings_dir = repo_root / ".claude"
settings_dir.mkdir(parents=True, exist_ok=True)
settings_path = settings_dir / "settings.json"

Expand Down Expand Up @@ -591,6 +603,7 @@ def inject_claude_md(repo_root: Path) -> None:
"GEMINI.md": ("antigravity",),
".cursorrules": ("cursor",),
".windsurfrules": ("windsurf",),
"QODER.md": ("qoder",),
}


Expand All @@ -615,3 +628,43 @@ def inject_platform_instructions(repo_root: Path, target: str = "all") -> list[s
if _inject_instructions(path, _CLAUDE_MD_SECTION_MARKER, _CLAUDE_MD_SECTION):
updated.append(filename)
return updated


def install_qoder_skills(repo_root: Path) -> Path | None:
"""Install skills to Qoder's project-level skills directory.

Qoder expects skills in .qoder/skills/{skillName}/SKILL.md format within the project.
This function copies the project's skills/ directory contents to that location.

Args:
repo_root: Repository root directory (where the skills/ folder is located).

Returns:
Path to the Qoder skills directory, or None if installation failed.
"""
# Qoder skills directory (project-level)
qoder_skills_dir = repo_root / ".qoder" / "skills"
qoder_skills_dir.mkdir(parents=True, exist_ok=True)

# Source skills directory in the project
source_skills_dir = repo_root / "skills"
if not source_skills_dir.exists():
logger.warning("No skills/ directory found in %s", repo_root)
return None

installed_count = 0
for skill_dir in source_skills_dir.iterdir():
if skill_dir.is_dir():
skill_file = skill_dir / "SKILL.md"
if skill_file.exists():
target_dir = qoder_skills_dir / skill_dir.name
target_dir.mkdir(parents=True, exist_ok=True)
target_file = target_dir / "SKILL.md"
target_file.write_text(skill_file.read_text(encoding="utf-8"), encoding="utf-8")
logger.info("Installed Qoder skill: %s", skill_dir.name)
installed_count += 1

if installed_count > 0:
logger.info("Installed %d skill(s) to %s", installed_count, qoder_skills_dir)
return qoder_skills_dir
return None
6 changes: 4 additions & 2 deletions diagrams/generate_diagrams.py
Original file line number Diff line number Diff line change
Expand Up @@ -595,6 +595,8 @@ def d8():
("Continue", "~/.continue/config.json", YLW, YLW_BG),
("OpenCode", ".opencode.json", RED, RED_BG),
("Antigravity", "~/.gemini/antigravity/mcp_config.json",GRY, GRY_BG),
("Qwen Code", "~/.qwen/settings.json", BLU, PRP_BG), # blue-purple
("Qoder", ".qoder/mcp.json", GRN, ORG_BG), # green-orange
]

# Central "install" node
Expand All @@ -604,8 +606,8 @@ def d8():

# Fan out to platforms
cols = len(platforms)
card_w, card_h = 140, 80
total_w = cols * card_w + (cols-1) * 20
card_w, card_h = 120, 80 # narrower cards for 9 platforms
total_w = cols * card_w + (cols-1) * 15 # tighter spacing
x0 = center_x - total_w/2
card_y = 360

Expand Down
5 changes: 4 additions & 1 deletion docs/USAGE.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,10 @@ code-review-graph install --platform claude-code
| **Windsurf** | `.windsurf/mcp.json` |
| **Zed** | `.zed/settings.json` |
| **Continue** | `.continue/config.json` |
| **OpenCode** | `.opencode/config.json` |
| **OpenCode** | `.opencode.json` |
| **Antigravity** | `~/.gemini/antigravity/mcp_config.json` |
| **Qwen Code** | `~/.qwen/settings.json` |
| **Qoder** | `.qoder/mcp.json` |

## Core Workflow

Expand Down
27 changes: 27 additions & 0 deletions skills/debug-issue/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
---
name: Debug Issue
description: Systematically debug issues using graph-powered code navigation
---

## Debug Issue

Use the knowledge graph to systematically trace and debug issues.

### Steps

1. Use `semantic_search_nodes` to find code related to the issue.
2. Use `query_graph` with `callers_of` and `callees_of` to trace call chains.
3. Use `get_flow` to see full execution paths through suspected areas.
4. Run `detect_changes` to check if recent changes caused the issue.
5. Use `get_impact_radius` on suspected files to see what else is affected.

### Tips

- Check both callers and callees to understand the full context.
- Look at affected flows to find the entry point that triggers the bug.
- Recent changes are the most common source of new issues.

## Token Efficiency Rules
- ALWAYS start with `get_minimal_context(task="<your task>")` before any other graph tool.
- Use `detail_level="minimal"` on all calls. Only escalate to "standard" when minimal is insufficient.
- Target: complete any review/debug/refactor task in ≤5 tool calls and ≤800 total output tokens.
28 changes: 28 additions & 0 deletions skills/explore-codebase/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
---
name: Explore Codebase
description: Navigate and understand codebase structure using the knowledge graph
---

## Explore Codebase

Use the code-review-graph MCP tools to explore and understand the codebase.

### Steps

1. Run `list_graph_stats` to see overall codebase metrics.
2. Run `get_architecture_overview` for high-level community structure.
3. Use `list_communities` to find major modules, then `get_community` for details.
4. Use `semantic_search_nodes` to find specific functions or classes.
5. Use `query_graph` with patterns like `callers_of`, `callees_of`, `imports_of` to trace relationships.
6. Use `list_flows` and `get_flow` to understand execution paths.

### Tips

- Start broad (stats, architecture) then narrow down to specific areas.
- Use `children_of` on a file to see all its functions and classes.
- Use `find_large_functions` to identify complex code.

## Token Efficiency Rules
- ALWAYS start with `get_minimal_context(task="<your task>")` before any other graph tool.
- Use `detail_level="minimal"` on all calls. Only escalate to "standard" when minimal is insufficient.
- Target: complete any review/debug/refactor task in ≤5 tool calls and ≤800 total output tokens.
28 changes: 28 additions & 0 deletions skills/refactor-safely/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
---
name: Refactor Safely
description: Plan and execute safe refactoring using dependency analysis
---

## Refactor Safely

Use the knowledge graph to plan and execute refactoring with confidence.

### Steps

1. Use `refactor_tool` with mode="suggest" for community-driven refactoring suggestions.
2. Use `refactor_tool` with mode="dead_code" to find unreferenced code.
3. For renames, use `refactor_tool` with mode="rename" to preview all affected locations.
4. Use `apply_refactor_tool` with the refactor_id to apply renames.
5. After changes, run `detect_changes` to verify the refactoring impact.

### Safety Checks

- Always preview before applying (rename mode gives you an edit list).
- Check `get_impact_radius` before major refactors.
- Use `get_affected_flows` to ensure no critical paths are broken.
- Run `find_large_functions` to identify decomposition targets.

## Token Efficiency Rules
- ALWAYS start with `get_minimal_context(task="<your task>")` before any other graph tool.
- Use `detail_level="minimal"` on all calls. Only escalate to "standard" when minimal is insufficient.
- Target: complete any review/debug/refactor task in ≤5 tool calls and ≤800 total output tokens.
29 changes: 29 additions & 0 deletions skills/review-changes/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
---
name: Review Changes
description: Perform a structured code review using change detection and impact
---

## Review Changes

Perform a thorough, risk-aware code review using the knowledge graph.

### Steps

1. Run `detect_changes` to get risk-scored change analysis.
2. Run `get_affected_flows` to find impacted execution paths.
3. For each high-risk function, run `query_graph` with pattern="tests_for" to check test coverage.
4. Run `get_impact_radius` to understand the blast radius.
5. For any untested changes, suggest specific test cases.

### Output Format

Provide findings grouped by risk level (high/medium/low) with:
- What changed and why it matters
- Test coverage status
- Suggested improvements
- Overall merge recommendation

## Token Efficiency Rules
- ALWAYS start with `get_minimal_context(task="<your task>")` before any other graph tool.
- Use `detail_level="minimal"` on all calls. Only escalate to "standard" when minimal is insufficient.
- Target: complete any review/debug/refactor task in ≤5 tool calls and ≤800 total output tokens.
Loading