Problem Statement
Spec Kit currently couples two separate concerns in specify extension add --dev:
- The extension source is a local directory.
- Generated agent artifacts are written as dev-mode symlinks where supported.
This creates a gap for private, repository-local extensions. A team may want to keep the extension source in the same repository as the codebase and install it locally as regular generated files, without publishing it to a catalog or release first.
Today, the practical options are:
specify extension add <extension-id>
This installs from a bundled extension or catalog entry and writes regular files, but it does not accept an arbitrary local extension directory.
specify extension add ./path/to/extension --dev --force
This accepts a local extension directory, but it writes symlinked agent artifacts. That is not safe for every agent integration. In particular, Codex does not reliably load symlinked skills under .agents/skills.
For a local extension such as:
.project-skills/
extension.yml
commands/
backend-rest-controllers.md
domain-data-model.md
...
running:
specify extension add .project-skills --dev --force
registers the extension, but the generated Codex skills become symlinks to .specify-dev. Those symlinked SKILL.md files are not reliably loaded by Codex.
This is especially problematic when the extension itself contains a refresh skill. In our workflow, agent instructions explain how to create or edit project-specific skills:
- Edit the extension source under
commands/.
- Update
extension.yml.
- Invoke the refresh skill so the local extension is reinstalled and the current agent receives the new or updated skill.
That makes refresh part of the normal agent-driven skill-authoring workflow, not just a manual maintenance step. If refresh installs symlinked skills, the workflow can leave Codex unable to use the skills it just refreshed.
Proposed Solution
Add a first-class way to install an extension from a local directory while writing normal generated files instead of symlinks.
One possible CLI design:
specify extension add ./path/to/extension --local --force
Where --local means: install this local directory as a regular extension install, not as a dev-linked install.
Another possible design:
specify extension add ./path/to/extension --force
Where a path containing extension.yml is treated as a normal local install by default, and --dev remains the opt-in mode for linked development behavior.
Expected result for Codex:
.specify/extensions/project-skills/
.agents/skills/speckit-project-skills-backend-rest-controllers/SKILL.md
.agents/skills/speckit-project-skills-domain-data-model/SKILL.md
...
Each generated SKILL.md should be a regular file, not a symlink.
This would keep the current --dev behavior available for users who want live linked artifacts, while supporting local/private extension installs that need regular files.
Alternatives Considered
--dev --no-symlinks
Another acceptable design would be:
specify extension add ./path/to/extension --dev --no-symlinks --force
This keeps the existing local-directory dev flow but disables symlink generation for agent artifacts.
That said, --dev --no-symlinks still mixes source location and output behavior under one dev mode. A separate regular local-install mode may be clearer because "local source directory" and "dev symlinks" are independent concerns.
Existing related issues and PRs
This request overlaps with, but is not fully covered by, existing issues:
PR #2988 would likely fix the immediate Codex-specific symptom, but this request is broader: local extension installation should not require dev symlinks or a published/cataloged package.
Manual symlink replacement
Users can install with --dev and then manually replace symlinked SKILL.md files with real copies.
This is too manual for an agent-driven refresh loop and easy to forget. It also makes the refresh skill responsible for compensating for installer behavior, which should not be necessary.
Publishing or packaging first
Users can publish or package the extension first and then install through a normal URL or catalog path.
That is unnecessary friction for private, repository-local extensions and does not fit workflows where the repository itself is the source of truth for the extension.
Component
Specify CLI (initialization, commands)
AI Agent (if applicable)
None
Use Cases
Repository-local skill ground truth
A repository can contain the ground truth for its own agent skills:
.project-skills/
extension.yml
commands/
The skills document how agents should work with that specific codebase, domain model, backend architecture, test strategy, operational workflows, and coding conventions.
Keeping the extension in the same repository has practical benefits:
- Skill changes are reviewed with normal code review.
- Skill source evolves with the code it describes.
- Branches can change both code and agent guidance together.
- The repository remains self-contained for onboarding.
Agent-agnostic skill source
Spec Kit extensions are useful as an agent-agnostic source of skills. The same commands/ markdown can be rendered into Codex, Claude, Copilot, Cursor, Gemini, or other agent-specific formats.
For this to work well, the source extension should be local and canonical, while generated agent artifacts should be ordinary installed outputs for the active agent.
Agent-driven skill authoring and refresh
The extension can include instructions that tell agents how to add or update project-specific skills:
- Create or edit a command markdown file.
- Register the command in
extension.yml.
- Run a refresh skill to reinstall the extension for the current agent.
This allows users to ask the agent to create or update a project skill without manually knowing the extension layout.
That workflow needs a refresh command that can install from the local source of truth and produce agent-loadable artifacts. For Codex, that means regular SKILL.md files under .agents/skills, not symlinks.
Private extensions that should not be published
Many project-specific skill extensions are private by nature. They may include internal architecture, domain concepts, deployment workflows, or proprietary conventions.
These extensions should not need a public release, catalog entry, or external package location before they can be installed as regular files in a local Spec Kit project.
Acceptance Criteria
Additional Context
No response
Problem Statement
Spec Kit currently couples two separate concerns in
specify extension add --dev:This creates a gap for private, repository-local extensions. A team may want to keep the extension source in the same repository as the codebase and install it locally as regular generated files, without publishing it to a catalog or release first.
Today, the practical options are:
This installs from a bundled extension or catalog entry and writes regular files, but it does not accept an arbitrary local extension directory.
This accepts a local extension directory, but it writes symlinked agent artifacts. That is not safe for every agent integration. In particular, Codex does not reliably load symlinked skills under
.agents/skills.For a local extension such as:
running:
registers the extension, but the generated Codex skills become symlinks to
.specify-dev. Those symlinkedSKILL.mdfiles are not reliably loaded by Codex.This is especially problematic when the extension itself contains a refresh skill. In our workflow, agent instructions explain how to create or edit project-specific skills:
commands/.extension.yml.That makes refresh part of the normal agent-driven skill-authoring workflow, not just a manual maintenance step. If refresh installs symlinked skills, the workflow can leave Codex unable to use the skills it just refreshed.
Proposed Solution
Add a first-class way to install an extension from a local directory while writing normal generated files instead of symlinks.
One possible CLI design:
Where
--localmeans: install this local directory as a regular extension install, not as a dev-linked install.Another possible design:
Where a path containing
extension.ymlis treated as a normal local install by default, and--devremains the opt-in mode for linked development behavior.Expected result for Codex:
Each generated
SKILL.mdshould be a regular file, not a symlink.This would keep the current
--devbehavior available for users who want live linked artifacts, while supporting local/private extension installs that need regular files.Alternatives Considered
--dev --no-symlinksAnother acceptable design would be:
This keeps the existing local-directory dev flow but disables symlink generation for agent artifacts.
That said,
--dev --no-symlinksstill mixes source location and output behavior under one dev mode. A separate regular local-install mode may be clearer because "local source directory" and "dev symlinks" are independent concerns.Existing related issues and PRs
This request overlaps with, but is not fully covered by, existing issues:
--devuse symlinks for extension agent artifacts.specify extension add --dev#2930 reports that Codex does not recognize symlinked skills generated byspecify extension add --dev.extension add --dev --forcedeletes the extension directory and registers nothing when source path == install path #2990 reports another sharp edge in the local--dev --forceworkflow when the source path is the install path.PR #2988 would likely fix the immediate Codex-specific symptom, but this request is broader: local extension installation should not require dev symlinks or a published/cataloged package.
Manual symlink replacement
Users can install with
--devand then manually replace symlinkedSKILL.mdfiles with real copies.This is too manual for an agent-driven refresh loop and easy to forget. It also makes the refresh skill responsible for compensating for installer behavior, which should not be necessary.
Publishing or packaging first
Users can publish or package the extension first and then install through a normal URL or catalog path.
That is unnecessary friction for private, repository-local extensions and does not fit workflows where the repository itself is the source of truth for the extension.
Component
Specify CLI (initialization, commands)
AI Agent (if applicable)
None
Use Cases
Repository-local skill ground truth
A repository can contain the ground truth for its own agent skills:
The skills document how agents should work with that specific codebase, domain model, backend architecture, test strategy, operational workflows, and coding conventions.
Keeping the extension in the same repository has practical benefits:
Agent-agnostic skill source
Spec Kit extensions are useful as an agent-agnostic source of skills. The same
commands/markdown can be rendered into Codex, Claude, Copilot, Cursor, Gemini, or other agent-specific formats.For this to work well, the source extension should be local and canonical, while generated agent artifacts should be ordinary installed outputs for the active agent.
Agent-driven skill authoring and refresh
The extension can include instructions that tell agents how to add or update project-specific skills:
extension.yml.This allows users to ask the agent to create or update a project skill without manually knowing the extension layout.
That workflow needs a refresh command that can install from the local source of truth and produce agent-loadable artifacts. For Codex, that means regular
SKILL.mdfiles under.agents/skills, not symlinks.Private extensions that should not be published
Many project-specific skill extensions are private by nature. They may include internal architecture, domain concepts, deployment workflows, or proprietary conventions.
These extensions should not need a public release, catalog entry, or external package location before they can be installed as regular files in a local Spec Kit project.
Acceptance Criteria
--devsymlink behavior remains available for users who want linked development artifacts..agents/skills/*/SKILL.mdfiles.--forceand does not delete the source directory if the source path is inside.specify/extensions.Additional Context
No response