fix #374 #401 #410 #413 #385: vscode install cmd, core.hooksPath, absolute cache root, Windows PATH docs, Kiro YAML colon

This commit is contained in:
Safi
2026-04-17 08:33:02 +01:00
parent 494f519bf4
commit a01e0981ed
6 changed files with 79 additions and 6 deletions
+3
View File
@@ -32,6 +32,9 @@ pip install graphifyy && graphify install
> The PyPI package is temporarily named `graphifyy` while the `graphify` name is being reclaimed. The CLI and skill command are still `graphify`.
> **Windows:** If `graphify` is not recognized after install, add the Python Scripts folder to your PATH: `%APPDATA%\Python\Python3xx\Scripts` (replace `3xx` with your Python version, e.g. `313`). Or use `pipx install graphifyy` which handles PATH automatically.
> **macOS (externally managed):** Use `pipx install graphifyy` if `pip install` fails with an "externally-managed-environment" error.
Then open Claude Code in any directory and type:
```
+43
View File
@@ -87,6 +87,41 @@ def claude_install(project_dir: Path | None = None) -> None:
print("codebase questions and rebuild it after code changes.")
_COPILOT_INSTRUCTIONS = """\
## graphify knowledge graph
This project has a graphify knowledge graph at graphify-out/.
- Before answering architecture or codebase questions, read graphify-out/GRAPH_REPORT.md for god nodes and community structure
- If graphify-out/wiki/index.md exists, navigate it instead of reading raw files
- After modifying code files, run: python3 -c "from graphify.watch import _rebuild_code; from pathlib import Path; _rebuild_code(Path('.'))"
"""
_COPILOT_MARKER = "## graphify knowledge graph"
def vscode_install(project_dir: Path | None = None) -> None:
"""Write graphify context to .github/copilot-instructions.md."""
base = (project_dir or Path(".")).resolve()
github_dir = base / ".github"
github_dir.mkdir(exist_ok=True)
target = github_dir / "copilot-instructions.md"
if target.exists():
content = target.read_text()
if _COPILOT_MARKER in content:
print("graphify already configured in .github/copilot-instructions.md")
return
target.write_text(content.rstrip() + "\n\n" + _COPILOT_INSTRUCTIONS)
else:
target.write_text(_COPILOT_INSTRUCTIONS)
print(f"graphify instructions written to {target}")
print()
print("GitHub Copilot Chat will now use the knowledge graph when answering")
print("questions about this codebase.")
def claude_uninstall(project_dir: Path | None = None) -> None:
"""Remove the graphify section from the local CLAUDE.md."""
target = (project_dir or Path(".")) / "CLAUDE.md"
@@ -123,6 +158,7 @@ def main() -> None:
print()
print("Commands:")
print(" install copy skill to ~/.claude/skills/ and register in CLAUDE.md")
print(" vscode install write graphify context to .github/copilot-instructions.md")
print(" benchmark [graph.json] measure token reduction vs naive full-corpus approach")
print(" hook install install post-commit git hook (auto-rebuilds graph on commit)")
print(" hook uninstall remove post-commit git hook")
@@ -135,6 +171,13 @@ def main() -> None:
cmd = sys.argv[1]
if cmd == "install":
install()
elif cmd == "vscode":
subcmd = sys.argv[2] if len(sys.argv) > 2 else ""
if subcmd == "install":
vscode_install()
else:
print("Usage: graphify vscode install", file=sys.stderr)
sys.exit(1)
elif cmd == "claude":
subcmd = sys.argv[2] if len(sys.argv) > 2 else ""
if subcmd == "install":
+1 -1
View File
@@ -13,7 +13,7 @@ def file_hash(path: Path) -> str:
def cache_dir(root: Path = Path(".")) -> Path:
"""Returns graphify-out/cache/ - creates it if needed."""
d = Path(root) / "graphify-out" / "cache"
d = Path(root).resolve() / "graphify-out" / "cache"
d.mkdir(parents=True, exist_ok=True)
return d
+30 -4
View File
@@ -1,5 +1,6 @@
# git hook integration - install/uninstall graphify post-commit hook
from __future__ import annotations
import subprocess
from pathlib import Path
_HOOK_MARKER = "# graphify-hook"
@@ -53,6 +54,32 @@ def _git_root(path: Path) -> Path | None:
return None
def _hooks_dir(root: Path) -> Path:
"""Return the active hooks directory for this repo.
Respects core.hooksPath if set (e.g. repos using Husky). Falls back to
.git/hooks so we never write hooks into the wrong location.
"""
try:
result = subprocess.run(
["git", "-C", str(root), "config", "core.hooksPath"],
capture_output=True, text=True,
)
if result.returncode == 0:
custom = result.stdout.strip()
if custom:
p = Path(custom)
if not p.is_absolute():
p = root / p
p.mkdir(parents=True, exist_ok=True)
return p
except (OSError, FileNotFoundError):
pass
d = root / ".git" / "hooks"
d.mkdir(exist_ok=True)
return d
def install(path: Path = Path(".")) -> str:
"""Install graphify post-commit hook in the nearest git repo.
@@ -62,8 +89,7 @@ def install(path: Path = Path(".")) -> str:
if root is None:
raise RuntimeError(f"No git repository found at or above {path.resolve()}")
hooks_dir = root / ".git" / "hooks"
hooks_dir.mkdir(exist_ok=True)
hooks_dir = _hooks_dir(root)
hook_path = hooks_dir / "post-commit"
if hook_path.exists():
@@ -85,7 +111,7 @@ def uninstall(path: Path = Path(".")) -> str:
if root is None:
raise RuntimeError(f"No git repository found at or above {path.resolve()}")
hook_path = root / ".git" / "hooks" / "post-commit"
hook_path = _hooks_dir(root) / "post-commit"
if not hook_path.exists():
return "No post-commit hook found - nothing to remove."
@@ -110,7 +136,7 @@ def status(path: Path = Path(".")) -> str:
root = _git_root(path)
if root is None:
return "Not in a git repository."
hook_path = root / ".git" / "hooks" / "post-commit"
hook_path = _hooks_dir(root) / "post-commit"
if not hook_path.exists():
return "graphify hook: not installed"
if _HOOK_MARKER in hook_path.read_text():
+1 -1
View File
@@ -1,6 +1,6 @@
---
name: graphify
description: any input (code, docs, papers, images) knowledge graph clustered communities HTML + JSON + audit report
description: "any input (code, docs, papers, images) - knowledge graph - clustered communities - HTML + JSON + audit report"
trigger: /graphify
---
+1
View File
@@ -23,6 +23,7 @@ def _rebuild_code(watch_path: Path) -> bool:
Returns True on success, False on error.
"""
watch_path = Path(watch_path).resolve()
try:
from graphify.extract import collect_files, extract
from graphify.build import build_from_json