Add Zed integration#2780
Conversation
There was a problem hiding this comment.
Pull request overview
Note
Copilot was unable to run its full agentic suite in this review.
Adds Zed editor as a new skills-based integration that installs Spec Kit commands as .agents/skills/speckit-<name>/SKILL.md files invokable via Zed's slash-command menu.
Changes:
- New
ZedIntegrationclass registered in the integrations registry - Hook invocation rendering and init-flow handling for
zedskill mode - Documentation, registry, and integration-test updates including a new
test_integration_zed.py
Reviewed changes
Copilot reviewed 9 out of 9 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| src/specify_cli/integrations/zed/init.py | New ZedIntegration (skills-based, .agents/skills, AGENTS.md) |
| src/specify_cli/integrations/init.py | Imports and registers ZedIntegration |
| src/specify_cli/extensions.py | Adds zed_skill_mode branch rendering /skill-name invocations |
| src/specify_cli/commands/init.py | Adds Zed to skill-mode flags, post-init step, and display command logic |
| docs/reference/integrations.md | Adds Zed row to integrations table |
| docs/index.md | Bumps integration count from 30 to 31 and lists Zed |
| tests/integrations/test_registry.py | Adds zed to expected-keys list |
| tests/integrations/test_integration_subcommand.py | Asserts zed appears in list output |
| tests/integrations/test_integration_zed.py | New tests for Zed integration and hook invocation rendering |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
mnriem
left a comment
There was a problem hiding this comment.
Please address Copilot feedback
…am/main resolving conflicts
|
Side note, I have been using it last couple days and it works as expected |
|
Please address Copilot feedback and the test & lint errors |
- Remove non-actionable --skills flag from ZedIntegration (Zed is always skills-based, like Agy) - Align zed_skill_mode predicate with ai_skills for consistency across init output and hook rendering - Consolidate claude/cursor/zed slash-skill return blocks in _render_hook_invocation to reduce duplication - Override test_options_include_skills_flag for Zed (no --skills flag)
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
- Make zed_skill_mode unconditional in hook rendering (Zed is always skills-based, no --skills option) - Add test_init_persists_ai_skills_for_zed that exercises the actual CLI init path and verifies HookExecutor renders /speckit-plan without manual init-options manipulation
mnriem
left a comment
There was a problem hiding this comment.
Please address Copilot feedback
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
- Update integration count from 31 to 33 in docs/index.md (32 integrations + Generic) - Make zed_skill_mode unconditional to match extensions.py behavior - Consolidate slash-skill integrations into a set for consistency - Move os import to module level in test_integration_zed.py
- Fix slash-skill integrations: Claude/Cursor require ai_skills=true; Zed/Agy/Devin are always skills - Allow --ai-skills with --integration (not just --ai) to fix validation error
| codex_skill_mode = selected_ai == "codex" and bool( | ||
| init_options.get("ai_skills") | ||
| ) | ||
| claude_skill_mode = selected_ai == "claude" and bool( | ||
| init_options.get("ai_skills") | ||
| ) | ||
| kimi_skill_mode = selected_ai == "kimi" | ||
| cursor_skill_mode = selected_ai == "cursor-agent" and bool(init_options.get("ai_skills")) | ||
| cursor_skill_mode = selected_ai == "cursor-agent" and bool( | ||
| init_options.get("ai_skills") | ||
| ) | ||
| zed_skill_mode = selected_ai == "zed" | ||
| cline_mode = selected_ai == "cline" |
| ai_skills: bool = typer.Option( | ||
| False, | ||
| "--ai-skills", | ||
| help="Install Prompt.MD templates as agent skills (requires --ai)", | ||
| ), |
- Add agy_skill_mode and devin_skill_mode variables to fix F841 lint error - Use all skill mode variables in the slash-skill conditional check - Update --ai-skills help text to reflect it works with --integration too
05b7fac to
04d3eb3
Compare
| init_options = self._load_init_options() | ||
| selected_ai = init_options.get("ai") | ||
| codex_skill_mode = selected_ai == "codex" and bool(init_options.get("ai_skills")) | ||
| claude_skill_mode = selected_ai == "claude" and bool(init_options.get("ai_skills")) | ||
| codex_skill_mode = selected_ai == "codex" and bool( | ||
| init_options.get("ai_skills") | ||
| ) | ||
| claude_skill_mode = selected_ai == "claude" and bool( | ||
| init_options.get("ai_skills") | ||
| ) | ||
| kimi_skill_mode = selected_ai == "kimi" | ||
| cursor_skill_mode = selected_ai == "cursor-agent" and bool(init_options.get("ai_skills")) | ||
| cursor_skill_mode = selected_ai == "cursor-agent" and bool( | ||
| init_options.get("ai_skills") | ||
| ) | ||
| zed_skill_mode = selected_ai == "zed" | ||
| agy_skill_mode = selected_ai == "agy" | ||
| devin_skill_mode = selected_ai == "devin" | ||
| cline_mode = selected_ai == "cline" | ||
|
|
||
| skill_name = self._skill_name_from_command(command_id) | ||
| if codex_skill_mode and skill_name: | ||
| return f"${skill_name}" | ||
| if claude_skill_mode and skill_name: | ||
| return f"/{skill_name}" | ||
| if kimi_skill_mode and skill_name: | ||
| return f"/skill:{skill_name}" | ||
| if cursor_skill_mode and skill_name: | ||
| return f"/{skill_name}" | ||
| if cline_mode: | ||
| from .integrations.cline import format_cline_command_name | ||
|
|
||
| return f"/{format_cline_command_name(command_id)}" | ||
|
|
||
| # Slash-skill integrations | ||
| # - Claude/Cursor: conditional on ai_skills flag | ||
| # - Zed/Agy/Devin: always skills-based | ||
| if skill_name and ( | ||
| claude_skill_mode | ||
| or cursor_skill_mode | ||
| or zed_skill_mode | ||
| or agy_skill_mode | ||
| or devin_skill_mode | ||
| ): | ||
| return f"/{skill_name}" |
| kimi_skill_mode = selected_ai == "kimi" | ||
| agy_skill_mode = selected_ai == "agy" and _is_skills_integration | ||
| trae_skill_mode = selected_ai == "trae" | ||
| cursor_agent_skill_mode = selected_ai == "cursor-agent" and (ai_skills or _is_skills_integration) | ||
| cursor_agent_skill_mode = selected_ai == "cursor-agent" and ( | ||
| ai_skills or _is_skills_integration | ||
| ) | ||
| copilot_skill_mode = selected_ai == "copilot" and _is_skills_integration | ||
| devin_skill_mode = selected_ai == "devin" | ||
| zed_skill_mode = selected_ai == "zed" | ||
| cline_skill_mode = selected_ai == "cline" | ||
| native_skill_mode = codex_skill_mode or claude_skill_mode or kimi_skill_mode or agy_skill_mode or trae_skill_mode or cursor_agent_skill_mode or copilot_skill_mode or devin_skill_mode | ||
| native_skill_mode = ( | ||
| codex_skill_mode | ||
| or claude_skill_mode | ||
| or kimi_skill_mode | ||
| or agy_skill_mode | ||
| or trae_skill_mode | ||
| or cursor_agent_skill_mode | ||
| or copilot_skill_mode | ||
| or devin_skill_mode | ||
| or zed_skill_mode | ||
| ) |
| ### Use any coding agent | ||
|
|
||
| <span class="pillar-stat">30 integrations</span> — Copilot, Gemini, Codex, Windsurf, Claude, Forge, Kiro, and more. Switch freely between agents with a single command. No lock-in. | ||
| <span class="pillar-stat">33 integrations</span> — Copilot, Gemini, Codex, Windsurf, Zed, Claude, Forge, Kiro, and more. Switch freely between agents with a single command. No lock-in. |
| </div> | ||
| <div class="stat-item"> | ||
| <span class="stat-number">30</span> | ||
| <span class="stat-number">33</span> |
|
Please address Copilot feedback and resolve conflicts by rebasing on upstream/main |
Summary
zedintegration that installs Spec Kit commands as Zed skills under.agents/skillsTesting
uv run --extra test python3 -m pytest tests/integrations/test_registry.py tests/integrations/test_integration_subcommand.py::TestIntegrationList::test_list_shows_available_integrations tests/integrations/test_integration_zed.py -qCloses #2779