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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ Full release notes with details on each version: [GitHub Releases](https://githu

## 0.9.36 (2026-08-07)

- Feature: new supported platform — Command Code (`graphify install --platform command-code`). The skill installs to `~/.commandcode/skills/graphify/` (user) or `.commandcode/skills/graphify/` (`--project`) with the full `references/` sidecar, and `graphify command-code install` wires the always-on `## graphify` section into `AGENTS.md`.
- Fix: four commands that failed silently while exiting 0 now surface the problem (#2534, thanks @elecnix). `cluster-only` warns when `--backend`/`--model`/`--batch-size` are ignored because saved labels are being reused; the community-label prompt no longer collides with the discard sentinel (a model echoing the key back is no longer silently dropped); `tree --root` exits non-zero when the root matches no source file instead of silently flattening the tree; and `cluster-only` stamps `built_at_commit` from the analysed graph rather than the shell's working directory. Also folds in the `cluster-only` refused-write guard from #2522 (thanks @aniJani).
- Fix: a Swift `extension Foo` in a different file from `Foo` no longer drops static and singleton call edges into the type (#2538, thanks @pawelo446). The extension node id is now remapped consistently so the extension merges onto its base type before call resolution, and the merge is gated so it never absorbs a same-named type from another language.
- Fix: node-id collision resolution is now deterministic and prefers active over archived paths (#2532, thanks @michaelxer for the active/archived idea in #2540). Two files that mint the same id (for example `plans/_done/x.md` vs `plans/in-progress/x.md`) are ranked by a lifecycle penalty computed on the root-relative path and a reversed-segment tie-break, so the winner no longer depends on ASCII filename order, absolute-vs-relative path form, or the checkout directory name.
Expand Down
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ graphify-out/
└── graph.json the full graph — query it anytime without re-reading your files
```

**Works in** Claude Code, Cursor, Codex, Gemini CLI, GitHub Copilot, and 15+ more — [pick your platform](#install).
**Works in** Claude Code, Cursor, Codex, Gemini CLI, GitHub Copilot, Command Code, and 15+ more — [pick your platform](#install).

---

Expand Down Expand Up @@ -229,6 +229,7 @@ for example `graphify claude install --project` or `graphify codex install --pro
| Agent Skills (cross-framework) | `graphify install --platform agents` (alias `--platform skills`) |
| Kiro IDE/CLI | `graphify kiro install` |
| Pi coding agent | `graphify install --platform pi` |
| Command Code | `graphify install --platform command-code` |
| Cursor | `graphify cursor install` |
| Devin CLI | `graphify devin install` |
| Google Antigravity | `graphify antigravity install` |
Expand Down Expand Up @@ -299,6 +300,7 @@ Run this once in your project after building a graph:
| Agent Skills (cross-framework) | `graphify agents install` (alias `graphify skills install`) |
| Kiro IDE/CLI | `graphify kiro install` |
| Pi coding agent | `graphify pi install` |
| Command Code | `graphify command-code install` |
| Devin CLI | `graphify devin install` |
| Google Antigravity | `graphify antigravity install` |

Expand Down Expand Up @@ -716,6 +718,8 @@ graphify pi install # skill file (Pi coding agent)
graphify pi uninstall
graphify devin install # skill file + .windsurf/rules/graphify.md (Devin CLI)
graphify devin uninstall
graphify command-code install # ~/.commandcode/skills/ + AGENTS.md (Command Code)
graphify command-code uninstall
graphify antigravity install # .agents/rules + .agents/workflows (Google Antigravity)
graphify antigravity uninstall

Expand Down
4 changes: 3 additions & 1 deletion graphify/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -507,7 +507,7 @@ def _run_cli() -> None:
print("Usage: graphify <command>")
print()
print("Commands:")
print(" install [--platform P] copy skill to platform config dir (claude|windows|codebuddy|codex|opencode|aider|amp|agents|claw|droid|trae|trae-cn|gemini|cursor|antigravity|hermes|kiro|pi|devin)")
print(" install [--platform P] copy skill to platform config dir (claude|windows|codebuddy|codex|opencode|aider|amp|agents|claw|droid|trae|trae-cn|gemini|cursor|antigravity|hermes|kiro|pi|devin|command-code)")
print(" uninstall remove graphify from all detected platforms in one shot")
print(" --purge also delete graphify-out/ directory")
print(" path \"A\" \"B\" shortest path between two nodes in graph.json")
Expand Down Expand Up @@ -692,6 +692,8 @@ def _run_cli() -> None:
print(" pi uninstall remove skill from ~/.pi/agent/skills/graphify/")
print(" devin install write skill to ~/.config/devin/skills/graphify/ (Devin CLI)")
print(" devin uninstall remove skill from ~/.config/devin/skills/graphify/")
print(" command-code install write skill to ~/.commandcode/skills/graphify/ + AGENTS.md (Command Code)")
print(" command-code uninstall remove skill from ~/.commandcode/skills/graphify/ + AGENTS.md section")
print()
return

Expand Down
26 changes: 23 additions & 3 deletions graphify/install.py
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,13 @@ def _platform_skill_destination(platform_name: str, *, project: bool = False, pr
# Global Antigravity skill dir (all workspaces): ~/.gemini/config/skills/
return Path.home() / ".gemini" / "config" / "skills" / "graphify" / "SKILL.md"

if platform_name == "command-code":
if project:
return (project_dir or Path(".")) / ".commandcode" / "skills" / "graphify" / "SKILL.md"
if os.environ.get("COMMANDCODE_CONFIG_DIR"):
return Path(os.environ["COMMANDCODE_CONFIG_DIR"]) / "skills" / "graphify" / "SKILL.md"
return Path.home() / ".commandcode" / "skills" / "graphify" / "SKILL.md"

cfg = _PLATFORM_CONFIG[platform_name]
if project:
return (project_dir or Path(".")) / cfg["skill_dst"]
Expand Down Expand Up @@ -455,6 +462,15 @@ def _skill_registration(skill_path: str = "~/.claude/skills/graphify/SKILL.md")
"claude_md": False,
"skill_refs": "agents",
},
"command-code": {
# Command Code discovers skills from .commandcode/skills/ (project) and
# ~/.commandcode/skills/ (user-global). The user-scope path is set in
# _platform_skill_destination (COMMANDCODE_CONFIG_DIR override).
"skill_file": "skill-command-code.md",
"skill_dst": Path(".commandcode") / "skills" / "graphify" / "SKILL.md",
"claude_md": False,
"skill_refs": "command-code",
},
"devin": {
# Monolith: devin ships the full SKILL.md inline, no references/ sidecar.
"skill_file": "skill-devin.md",
Expand Down Expand Up @@ -1560,7 +1576,7 @@ def _project_install(platform_name: str, project_dir: Path | None = None, strict
elif platform_name == "kiro":
_kiro_install(project_dir)
_print_project_git_add_hint([project_dir / ".kiro"])
elif platform_name in ("aider", "amp", "codex", "opencode", "claw", "droid", "trae", "trae-cn", "hermes"):
elif platform_name in ("aider", "amp", "codex", "opencode", "claw", "droid", "trae", "trae-cn", "hermes", "command-code"):
skill_dst = _copy_skill_file(platform_name, project=True, project_dir=project_dir)
_agents_install(project_dir, platform_name)
hint_paths = [_project_scope_root(skill_dst, project_dir), project_dir / "AGENTS.md"]
Expand Down Expand Up @@ -1601,7 +1617,7 @@ def _project_uninstall(platform_name: str, project_dir: Path | None = None) -> N
_cursor_uninstall(project_dir)
elif platform_name == "kiro":
_kiro_uninstall(project_dir)
elif platform_name in ("aider", "amp", "codex", "opencode", "claw", "droid", "trae", "trae-cn", "hermes"):
elif platform_name in ("aider", "amp", "codex", "opencode", "claw", "droid", "trae", "trae-cn", "hermes", "command-code"):
_remove_skill_file(platform_name, project=True, project_dir=project_dir)
_agents_uninstall(project_dir, platform=platform_name)
if platform_name == "codex":
Expand Down Expand Up @@ -1798,6 +1814,9 @@ def uninstall_all(project_dir: Path | None = None, purge: bool = False) -> None:
# The generic agents platform's user-scope skill lives at ~/.agents/skills,
# which neither the AGENTS.md cleanup nor amp's removal reaches.
_remove_skill_file("agents")
# Command Code's user-scope skill lives at ~/.commandcode/skills, which the
# AGENTS.md cleanup does not touch either.
_remove_skill_file("command-code")
_uninstall_opencode_plugin(pd)
_uninstall_codex_hook(pd)

Expand Down Expand Up @@ -1994,6 +2013,7 @@ def codebuddy_uninstall(project_dir: Path | None = None, *, project: bool = Fals
"claw",
"codebuddy",
"codex",
"command-code",
"copilot",
"cursor",
"devin",
Expand Down Expand Up @@ -2256,7 +2276,7 @@ def dispatch_install_cli(cmd: str) -> bool:
else:
print(f"Usage: graphify {cmd} [install|uninstall]", file=sys.stderr)
sys.exit(1)
elif cmd in ("aider", "codex", "opencode", "claw", "droid", "trae", "trae-cn", "hermes"):
elif cmd in ("aider", "codex", "opencode", "claw", "droid", "trae", "trae-cn", "hermes", "command-code"):
subcmd = sys.argv[2] if len(sys.argv) > 2 else ""
if subcmd == "install":
if "--project" in sys.argv[3:]:
Expand Down
Loading