Files
github-spec-kit/docs/local-development.md
Pascal THUET 9cd20c6c25 feat(dev): add integration scaffolder (#2685)
* feat(dev): add integration scaffolder

* fix(dev): address integration scaffold review feedback

* fix(dev): address scaffold follow-up review

* Potential fix for pull request finding

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

* fix(dev): default scaffolded integrations to multi_install_safe = False

The scaffold template emitted `multi_install_safe = True` alongside a
placeholder `context_file = "AGENTS.md"`. Registered as-is, that violates the
registry contract (test_safe_integrations_have_distinct_context_files): codex
already pairs AGENTS.md with multi_install_safe = True, so the generated
boilerplate would collide on first registration.

Default the scaffold to False (matching IntegrationBase) so generated code is
registry-test-friendly out of the box; contributors opt in once they pick a
unique context_file. Aligns the generated test skeleton and both scaffold
tests, which previously contradicted each other (one expected True, one False).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(dev): harden scaffold writes and accept case-insensitive --type

- Guard scaffold_integration() against symlinked target directories: walk
  each path component under the repo root and refuse symlinked dirs, then
  confirm the write destination resolves inside the repo (mirrors the
  manifest directory guard). Prevents scaffolding outside the repo when a
  contributor's integrations/tests path is symlinked.
- Make the `--type` click.Choice case-insensitive so `--type YAML` is
  accepted, matching scaffold_integration()'s strip()/lower() normalization
  instead of rejecting at the CLI layer.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(dev): report scaffold filesystem failures as a clean CLI error

The `dev integration scaffold` command only caught FileExistsError/ValueError,
so an OSError raised during mkdir()/write_text() (permission denied, read-only
checkout, a path component that is a file, ...) bubbled up as a traceback
instead of a clean error + exit code. Broaden the handler to OSError (which
also covers FileExistsError) and add coverage for the filesystem-error path.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(dev): move scaffold command under integration

* fix(dev): roll back partial scaffold writes

* fix(dev): correct lint docs and generated test docstring

- local-development.md: ruff check src/ is enforced in CI, not absent
- scaffolded test docstring: drop misleading 'scaffold' wording

* fix(scaffold): create only leaf integration directory

---------

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-16 17:48:40 -05:00

5.8 KiB

Local Development Guide

This guide shows how to iterate on the specify CLI locally without publishing a release or committing to main first.

Scripts now have both Bash (.sh) and PowerShell (.ps1) variants. The CLI auto-selects based on OS unless you pass --script sh|ps.

1. Clone and Switch Branches

git clone https://github.com/github/spec-kit.git
cd spec-kit
# Work on a feature branch
git checkout -b your-feature-branch

2. Run the CLI Directly (Fastest Feedback)

You can execute the CLI via the module entrypoint without installing anything:

# From repo root
python -m src.specify_cli --help
python -m src.specify_cli init demo-project --integration claude --ignore-agent-tools --script sh

If you prefer invoking the script file style (uses shebang):

python src/specify_cli/__init__.py init demo-project --script ps

3. Use Editable Install (Isolated Environment)

Create an isolated environment using uv so dependencies resolve exactly like end users get them:

# Create & activate virtual env (uv auto-manages .venv)
uv venv
source .venv/bin/activate  # or on Windows PowerShell: .venv\Scripts\Activate.ps1

# Install project in editable mode
uv pip install -e .

# Now 'specify' entrypoint is available
specify --help

Re-running after code edits requires no reinstall because of editable mode.

4. Invoke with uvx Directly From Git (Current Branch)

uvx can run from a local path (or a Git ref) to simulate user flows:

uvx --from . specify init demo-uvx --integration copilot --ignore-agent-tools --script sh

You can also point uvx at a specific branch without merging:

# Push your working branch first
git push origin your-feature-branch
uvx --from git+https://github.com/github/spec-kit.git@your-feature-branch specify init demo-branch-test --script ps

4a. Absolute Path uvx (Run From Anywhere)

If you're in another directory, use an absolute path instead of .:

uvx --from /mnt/c/GitHub/spec-kit specify --help
uvx --from /mnt/c/GitHub/spec-kit specify init demo-anywhere --integration copilot --ignore-agent-tools --script sh

Set an environment variable for convenience:

export SPEC_KIT_SRC=/mnt/c/GitHub/spec-kit
uvx --from "$SPEC_KIT_SRC" specify init demo-env --integration copilot --ignore-agent-tools --script ps

(Optional) Define a shell function:

specify-dev() { uvx --from /mnt/c/GitHub/spec-kit specify "$@"; }
# Then
specify-dev --help

5. Testing Script Permission Logic

After running an init, check that shell scripts are executable on POSIX systems:

ls -l scripts | grep .sh
# Expect owner execute bit (e.g. -rwxr-xr-x)

On Windows you will instead use the .ps1 scripts (no chmod needed).

6. Scaffold a Built-In Integration

Use the integration scaffold command to create the initial Python package and test skeleton for a new built-in integration:

specify integration scaffold my-agent --type markdown
specify integration scaffold my-agent --type toml
specify integration scaffold my-agent --type yaml
specify integration scaffold my-agent --type skills

Hyphenated keys are converted to Python-safe package names, for example my-agent creates src/specify_cli/integrations/my_agent/ and tests/integrations/test_integration_my_agent.py.

The scaffold does not register the integration automatically. Review the generated metadata, then add the import and _register() call in src/specify_cli/integrations/__init__.py.

7. Run Lint / Basic Checks

CI enforces ruff check src/ (see .github/workflows/test.yml), so run it locally before pushing:

uvx ruff check src/

You can also quickly sanity check importability:

python -c "import specify_cli; print('Import OK')"

8. Build a Wheel Locally (Optional)

Validate packaging before publishing:

uv build
ls dist/

Install the built artifact into a fresh throwaway environment if needed.

9. Using a Temporary Workspace

When testing init --here in a dirty directory, create a temp workspace:

mkdir /tmp/spec-test && cd /tmp/spec-test
python -m src.specify_cli init --here --integration claude --ignore-agent-tools --script sh  # if repo copied here

Or copy only the modified CLI portion if you want a lighter sandbox.

10. Debug Network / TLS Issues

Deprecated: The --skip-tls flag is a no-op and has no effect. It was previously used to bypass TLS validation during local testing. If you encounter TLS errors (e.g., on a corporate network), configure your environment's certificate store or proxy instead.

For example, set SSL_CERT_FILE or configure HTTPS_PROXY / HTTP_PROXY.

11. Rapid Edit Loop Summary

Action Command
Run CLI directly python -m src.specify_cli --help
Editable install uv pip install -e . then specify ...
Local uvx run (repo root) uvx --from . specify ...
Local uvx run (abs path) uvx --from /mnt/c/GitHub/spec-kit specify ...
Git branch uvx uvx --from git+URL@branch specify ...
Build wheel uv build

12. Cleaning Up

Remove build artifacts / virtual env quickly:

rm -rf .venv dist build *.egg-info

13. Common Issues

Symptom Fix
ModuleNotFoundError: typer Run uv pip install -e .
Scripts not executable (Linux) Re-run init or chmod +x scripts/*.sh
Git commands unavailable Install the git extension with specify extension add git
Wrong script type downloaded Pass --script sh or --script ps explicitly
TLS errors on corporate network Configure your environment's certificate store or proxy. The --skip-tls flag is deprecated and has no effect.

14. Next Steps

  • Update docs and run through Quick Start using your modified CLI
  • Open a PR when satisfied
  • (Optional) Tag a release once changes land in main