Skip to content

Commit 8eb703c

Browse files
committed
feat: implement Windsurf integration for graphify
- Add 'windsurf' platform to _PLATFORM_CONFIG in graphify/__main__.py - Implement _windsurf_install and _windsurf_uninstall for project-level rules - Register /graphify slash command via .windsurf/workflows/graphify.md - Append always-on context rules to .windsurfrules - Add skill-windsurf.md with complete agent logic for Windsurf/Codeium - Update README.md with Windsurf installation instructions
1 parent 625ca0e commit 8eb703c

5 files changed

Lines changed: 1319 additions & 3 deletions

File tree

.windsurf/workflows/graphify.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
---
2+
auto_execution_mode: 0
3+
description: Turn any folder of files into a navigable knowledge graph with community detection, an honest audit trail, and three outputs: interactive HTML, GraphRAG-ready JSON, and a plain-language GRAPH_REPORT.md.
4+
---
5+
6+
Run the graphify knowledge-graph pipeline.
7+
8+
1. Read the full step-by-step instructions from `~/.codeium/windsurf/skills/graphify/SKILL.md`.
9+
2. Execute those instructions on the path provided by the user (default: `.`).
10+
3. If `~/.codeium/windsurf/skills/graphify/SKILL.md` is not found, tell the user to run `graphify install --platform windsurf` first, then retry.

.windsurfrules

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
## graphify
2+
3+
This project has a graphify knowledge graph at graphify-out/.
4+
5+
Rules:
6+
- Before answering architecture or codebase questions, read graphify-out/GRAPH_REPORT.md for god nodes and community structure
7+
- If graphify-out/wiki/index.md exists, navigate it instead of reading raw files
8+
- After modifying code files in this session, run `python3 -c "from graphify.watch import _rebuild_code; from pathlib import Path; _rebuild_code(Path('.'))"` to keep the graph current
9+
## graphify
10+
11+
This project has a graphify knowledge graph at graphify-out/.
12+
13+
Rules:
14+
- Before answering architecture or codebase questions, read graphify-out/GRAPH_REPORT.md for god nodes and community structure
15+
- If graphify-out/wiki/index.md exists, navigate it instead of reading raw files
16+
- After modifying code files in this session, run `python3 -c "from graphify.watch import _rebuild_code; from pathlib import Path; _rebuild_code(Path('.'))"` to keep the graph current

README.md

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,8 +71,9 @@ pip install graphifyy && graphify install
7171
| Trae CN | `graphify install --platform trae-cn` |
7272
| Gemini CLI | `graphify install --platform gemini` |
7373
| Cursor | `graphify cursor install` |
74+
| Windsurf | `graphify install --platform windsurf` |
7475

75-
Codex users also need `multi_agent = true` under `[features]` in `~/.codex/config.toml` for parallel extraction. Factory Droid uses the `Task` tool for parallel subagent dispatch. OpenClaw and Aider use sequential extraction (parallel agent support is still early on those platforms). Trae uses the Agent tool for parallel subagent dispatch and does **not** support PreToolUse hooks — AGENTS.md is the always-on mechanism.
76+
Codex users also need `multi_agent = true` under `[features]` in `~/.codex/config.toml` for parallel extraction. Factory Droid uses the `Task` tool for parallel subagent dispatch. OpenClaw, Aider, and Windsurf use sequential extraction (Windsurf's parallel agents run in separate worktrees, not via programmatic spawning within a Cascade session). Trae uses the Agent tool for parallel subagent dispatch and does **not** support PreToolUse hooks — AGENTS.md is the always-on mechanism.
7677

7778
Then open your AI coding assistant and type:
7879

@@ -99,6 +100,7 @@ After building a graph, run this once in your project:
99100
| Trae CN | `graphify trae-cn install` |
100101
| Cursor | `graphify cursor install` |
101102
| Gemini CLI | `graphify gemini install` |
103+
| Windsurf | `graphify windsurf install` |
102104

103105
**Claude Code** does two things: writes a `CLAUDE.md` section telling Claude to read `graphify-out/GRAPH_REPORT.md` before answering architecture questions, and installs a **PreToolUse hook** (`settings.json`) that fires before every Glob and Grep call. If a knowledge graph exists, Claude sees: _"graphify: Knowledge graph exists. Read GRAPH_REPORT.md for god nodes and community structure before searching raw files."_ — so Claude navigates via the graph instead of grepping through every file.
104106

@@ -110,7 +112,9 @@ After building a graph, run this once in your project:
110112

111113
**Gemini CLI** copies the skill to `~/.gemini/skills/graphify/SKILL.md`, writes a `GEMINI.md` section, and installs a `BeforeTool` hook in `.gemini/settings.json` that fires before file-read tool calls — same always-on mechanism as Claude Code.
112114

113-
**Aider and OpenClaw, Factory Droid, Trae** write the same rules to `AGENTS.md` in your project root. These platforms don't support tool hooks, so AGENTS.md is the always-on mechanism.
115+
**Aider, OpenClaw, Factory Droid, and Trae** write the same rules to `AGENTS.md` in your project root. These platforms don't support tool hooks, so AGENTS.md is the always-on mechanism.
116+
117+
**Windsurf** writes `.windsurf/workflows/graphify.md` (registers `/graphify` as a Cascade slash command) and appends a `## graphify` section to `.windsurfrules` for always-on context. Run `graphify install --platform windsurf` separately to copy the full skill logic to `~/.codeium/windsurf/skills/graphify/SKILL.md`.
114118

115119
**GitHub Copilot CLI** copies the skill to `~/.copilot/skills/graphify/SKILL.md`. Run `graphify copilot install` to set it up.
116120

graphify/__main__.py

Lines changed: 103 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,11 @@ def _check_skill_version(skill_dst: Path) -> None:
9292
"skill_dst": Path(".trae-cn") / "skills" / "graphify" / "SKILL.md",
9393
"claude_md": False,
9494
},
95+
"windsurf": {
96+
"skill_file": "skill-windsurf.md",
97+
"skill_dst": Path(".codeium") / "windsurf" / "skills" / "graphify" / "SKILL.md",
98+
"claude_md": False,
99+
},
95100
"windows": {
96101
"skill_file": "skill-windows.md",
97102
"skill_dst": Path(".claude") / "skills" / "graphify" / "SKILL.md",
@@ -533,6 +538,92 @@ def _agents_uninstall(project_dir: Path) -> None:
533538
_uninstall_opencode_plugin(project_dir or Path("."))
534539

535540

541+
_WINDSURF_RULES_SECTION = """\
542+
543+
## graphify
544+
545+
This project has a graphify knowledge graph at graphify-out/.
546+
547+
Rules:
548+
- Before answering architecture or codebase questions, read graphify-out/GRAPH_REPORT.md for god nodes and community structure
549+
- If graphify-out/wiki/index.md exists, navigate it instead of reading raw files
550+
- After modifying code files in this session, run `python3 -c "from graphify.watch import _rebuild_code; from pathlib import Path; _rebuild_code(Path('.'))"` to keep the graph current
551+
"""
552+
553+
_WINDSURF_RULES_MARKER = "\n## graphify"
554+
555+
_WINDSURF_WORKFLOW = """\
556+
---
557+
title: graphify
558+
description: Turn any folder of files into a navigable knowledge graph with community detection, an honest audit trail, and three outputs: interactive HTML, GraphRAG-ready JSON, and a plain-language GRAPH_REPORT.md.
559+
---
560+
561+
Run the graphify knowledge-graph pipeline.
562+
563+
1. Read the full step-by-step instructions from `~/.codeium/windsurf/skills/graphify/SKILL.md`.
564+
2. Execute those instructions on the path provided by the user (default: `.`).
565+
3. If `~/.codeium/windsurf/skills/graphify/SKILL.md` is not found, tell the user to run `graphify install --platform windsurf` first, then retry.
566+
"""
567+
568+
569+
def _windsurf_install(project_dir: Path) -> None:
570+
"""Write .windsurf/workflows/graphify.md and append to .windsurfrules."""
571+
# 1. Workflow file — registers /graphify as a Cascade slash command
572+
workflow_path = project_dir / ".windsurf" / "workflows" / "graphify.md"
573+
workflow_path.parent.mkdir(parents=True, exist_ok=True)
574+
if workflow_path.exists():
575+
print(f" .windsurf/workflows/graphify.md -> already exists (no change)")
576+
else:
577+
workflow_path.write_text(_WINDSURF_WORKFLOW, encoding="utf-8")
578+
print(f" .windsurf/workflows/graphify.md -> written (/graphify slash command registered)")
579+
580+
# 2. Always-on rules via .windsurfrules
581+
rules_path = project_dir / ".windsurfrules"
582+
if rules_path.exists():
583+
content = rules_path.read_text(encoding="utf-8")
584+
if _WINDSURF_RULES_MARKER in content:
585+
print(f" .windsurfrules -> graphify section already present (no change)")
586+
else:
587+
rules_path.write_text(content.rstrip() + _WINDSURF_RULES_SECTION, encoding="utf-8")
588+
print(f" .windsurfrules -> graphify section appended")
589+
else:
590+
rules_path.write_text(_WINDSURF_RULES_SECTION.lstrip(), encoding="utf-8")
591+
print(f" .windsurfrules -> created")
592+
593+
print()
594+
print("Windsurf (Cascade) will now expose /graphify as a slash command.")
595+
print("The knowledge graph rules are active in every session via .windsurfrules.")
596+
print()
597+
print("Also run: graphify install --platform windsurf")
598+
print(" to copy the full skill logic to ~/.codeium/windsurf/skills/graphify/SKILL.md")
599+
600+
601+
def _windsurf_uninstall(project_dir: Path) -> None:
602+
"""Remove .windsurf/workflows/graphify.md and graphify section from .windsurfrules."""
603+
# Remove workflow file
604+
workflow_path = project_dir / ".windsurf" / "workflows" / "graphify.md"
605+
if workflow_path.exists():
606+
workflow_path.unlink()
607+
print(f" .windsurf/workflows/graphify.md -> removed")
608+
else:
609+
print(" .windsurf/workflows/graphify.md -> not found (nothing to remove)")
610+
611+
# Remove graphify section from .windsurfrules
612+
rules_path = project_dir / ".windsurfrules"
613+
if not rules_path.exists():
614+
return
615+
content = rules_path.read_text(encoding="utf-8")
616+
if _WINDSURF_RULES_MARKER not in content:
617+
return
618+
cleaned = re.sub(r"\n*\n## graphify\n.*?(?=\n## |\Z)", "", content, flags=re.DOTALL).rstrip()
619+
if cleaned:
620+
rules_path.write_text(cleaned + "\n", encoding="utf-8")
621+
print(f" .windsurfrules -> graphify section removed")
622+
else:
623+
rules_path.unlink()
624+
print(f" .windsurfrules -> was empty after removal, deleted")
625+
626+
536627
def claude_install(project_dir: Path | None = None) -> None:
537628
"""Write the graphify section to the local CLAUDE.md."""
538629
target = (project_dir or Path(".")) / "CLAUDE.md"
@@ -637,7 +728,7 @@ def main() -> None:
637728
print("Usage: graphify <command>")
638729
print()
639730
print("Commands:")
640-
print(" install [--platform P] copy skill to platform config dir (claude|windows|codex|opencode|aider|claw|droid|trae|trae-cn|gemini|cursor)")
731+
print(" install [--platform P] copy skill to platform config dir (claude|windows|codex|opencode|aider|claw|droid|trae|trae-cn|gemini|cursor|windsurf)")
641732
print(" query \"<question>\" BFS traversal of graph.json for a question")
642733
print(" --dfs use depth-first instead of breadth-first")
643734
print(" --budget N cap output at N tokens (default 2000)")
@@ -674,6 +765,8 @@ def main() -> None:
674765
print(" trae uninstall remove graphify section from AGENTS.md")
675766
print(" trae-cn install write graphify section to AGENTS.md (Trae CN)")
676767
print(" trae-cn uninstall remove graphify section from AGENTS.md")
768+
print(" windsurf install write .windsurf/workflows/graphify.md + .windsurfrules section (Windsurf)")
769+
print(" windsurf uninstall remove workflow and .windsurfrules section")
677770
print()
678771
return
679772

@@ -743,6 +836,15 @@ def main() -> None:
743836
else:
744837
print("Usage: graphify copilot [install|uninstall]", file=sys.stderr)
745838
sys.exit(1)
839+
elif cmd == "windsurf":
840+
subcmd = sys.argv[2] if len(sys.argv) > 2 else ""
841+
if subcmd == "install":
842+
_windsurf_install(Path("."))
843+
elif subcmd == "uninstall":
844+
_windsurf_uninstall(Path("."))
845+
else:
846+
print("Usage: graphify windsurf [install|uninstall]", file=sys.stderr)
847+
sys.exit(1)
746848
elif cmd in ("aider", "codex", "opencode", "claw", "droid", "trae", "trae-cn"):
747849
subcmd = sys.argv[2] if len(sys.argv) > 2 else ""
748850
if subcmd == "install":

0 commit comments

Comments
 (0)