Conversation
…er integration
An extension can ship subagent definitions and verbatim project files. provides.agents lands in the active integration's agent directory (a new agents_dir on the integration: .claude/agents for Claude Code, .cursor/agents for Cursor; an integration without one skips them with a note). provides.files copies a file to a declared project-relative dest, with {integration_folder}/ resolving to the active integration's folder and .specify/ off limits. Both are recorded in the registry with a content hash, so a file a person edited since is never overwritten on reinstall nor deleted on removal.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Contributor
There was a problem hiding this comment.
🟡 Changes recommended
Symlink traversal, integration-switch lifecycle gaps, ownership collisions, and incorrect versioning remain unresolved.
Get a fresh assessment by requesting another Copilot review.
Pull request overview
Adds hash-tracked extension-provided subagents and project files.
Changes:
- Validates, installs, tracks, and removes new artifact types.
- Adds Claude and Cursor agent directories.
- Adds tests and documentation.
File summaries
| File | Description |
|---|---|
src/specify_cli/extensions/__init__.py |
Implements artifact lifecycle and safety checks. |
src/specify_cli/integrations/base.py |
Defines optional agent directory metadata. |
src/specify_cli/integrations/claude/__init__.py |
Configures Claude’s agent directory. |
src/specify_cli/integrations/cursor_agent/__init__.py |
Configures Cursor’s agent directory. |
tests/test_extension_agents_files.py |
Tests validation and file ownership behavior. |
docs/reference/extensions.md |
Documents the new manifest fields. |
CHANGELOG.md |
Records the feature. |
pyproject.toml |
Updates package version metadata. |
Review details
- Files reviewed: 8/8 changed files
- Comments generated: 4
- Review effort level: Balanced
💡 Configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Comment on lines
+1963
to
+1967
| def _ensure_inside_project(self, dest: Path) -> None: | ||
| normalized = Path(os.path.normpath(dest)) | ||
| root = Path(os.path.normpath(self.project_root)) | ||
| if not normalized.is_relative_to(root): | ||
| raise ExtensionError(f"Destination {dest} escapes the project root") |
| [project] | ||
| name = "specify-cli" | ||
| version = "1.0.6.dev0" | ||
| version = "1.0.6" |
Comment on lines
+1986
to
+1988
| if previously is None and current != self._file_sha256(source): | ||
| _note(f"[yellow]⚠[/yellow] {rel} exists and is not this extension's; left alone") | ||
| return False |
Comment on lines
+2793
to
+2796
| # Subagent definitions and verbatim project files (provides.agents / | ||
| # provides.files) land in the active integration's own directories. | ||
| registered_agents = self._register_extension_agents(manifest, dest_dir) | ||
| registered_files = self._install_extension_files(manifest, dest_dir) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Two artifact kinds an extension can ship that Spec Kit does not model today:
provides.agents— subagent definitions (Markdown with frontmatter: name, description, model, tools). They land in the active integration's subagent directory through a newagents_dirclass attribute on the integration:.claude/agentsfor Claude Code,.cursor/agentsfor Cursor. An integration without a file-based subagent lane (Codex today) skips them with a one-line note; nothing else changes.provides.files— verbatim project files copied to a declareddest, for harness features Spec Kit has no primitive for (a Claude Code Workflow script under.claude/workflows/, say).{integration_folder}/at the start ofdestresolves to the active integration's folder; a destination may not be absolute, climb out of the project, or land under.specify/.Both are recorded in the extension registry with a content hash (
registered_agents,registered_files). On reinstall (--force) or removal, a file a person edited since is left alone and reported; only unchanged copies are replaced or deleted. Manifest validation reuses_validate_provided_artifactsfor name/file safety and addsproject_dest_violationfor destinations.Why: an engineering workflow whose economics come from model tiers (a Haiku explorer, Sonnet implementers, an Opus reviewer per ticket) needs per-agent
model:/tools:, which a forked skill cannot carry, and its fan-out stages are Workflow scripts. Both are files under the harness's own directory; the registrar already writes there, it only lacked the two kinds. Codex/Cursor both support subagents, so this is not a single-harness lane.Testing
uv run specify --helptests/test_extensions.py tests/test_extension_skills.py tests/test_agent_config_consistency.py tests/extensions— 907 passed, 68 skippedtests/test_extension_agents_files.py: manifest validation and bad destinations; Claude install places both and removal cleans them; a locally edited file survives--forceand removal; Cursor gets.cursor/agents, Codex gets files only; an extension of only agents/files is validspecify init --integration claudeprojectDocs:
docs/reference/extensions.mdgains a "Subagent Definitions and Project Files" section;CHANGELOG.mdhas an Unreleased entry.AI Disclosure
Code, tests and docs were generated with Claude Code and reviewed by the author; the design (which artifact kinds, hash-tracked ownership, the
{integration_folder}token, no.specify/destinations) was decided by the author.🤖 Generated with Claude Code