Skip to content

fix(init): generate root CLAUDE.md for --ai claude#1988

Open
arun-gupta wants to merge 2 commits intogithub:mainfrom
arun-gupta:fix-claude-md-init-1983
Open

fix(init): generate root CLAUDE.md for --ai claude#1988
arun-gupta wants to merge 2 commits intogithub:mainfrom
arun-gupta:fix-claude-md-init-1983

Conversation

@arun-gupta
Copy link

Ensure specify init --ai claude creates a minimal root CLAUDE.md pointing to .specify/memory/constitution.md

Made-with: Cursor

Description

Fixes #1983

Testing

Ran the tests on my machine.

  • [] Tested locally with uv run specify --help
  • Ran existing tests with uv sync && uv run pytest

Here is the output:

(specify-cli) arungupta@Mac spec-kit % python -m pytest tests/test_ai_skills.py
========================================================== test session starts ==========================================================
platform darwin -- Python 3.13.5, pytest-9.0.2, pluggy-1.6.0 -- /Users/arungupta/workspaces/spec-kit/.venv/bin/python3
cachedir: .pytest_cache
rootdir: /Users/arungupta/workspaces/spec-kit
configfile: pyproject.toml
plugins: cov-7.1.0, anyio-4.13.0
collected 98 items                                                                                                                      

tests/test_ai_skills.py::TestGetSkillsDir::test_claude_skills_dir PASSED                                                          [  1%]
tests/test_ai_skills.py::TestGetSkillsDir::test_gemini_skills_dir PASSED                                                          [  2%]
tests/test_ai_skills.py::TestGetSkillsDir::test_tabnine_skills_dir PASSED                                                         [  3%]
tests/test_ai_skills.py::TestGetSkillsDir::test_copilot_skills_dir PASSED                                                         [  4%]
tests/test_ai_skills.py::TestGetSkillsDir::test_codex_skills_dir_from_agent_config PASSED                                         [  5%]
tests/test_ai_skills.py::TestGetSkillsDir::test_cursor_agent_skills_dir PASSED                                                    [  6%]
tests/test_ai_skills.py::TestGetSkillsDir::test_kiro_cli_skills_dir PASSED                                                        [  7%]
tests/test_ai_skills.py::TestGetSkillsDir::test_pi_skills_dir PASSED                                                              [  8%]
tests/test_ai_skills.py::TestGetSkillsDir::test_unknown_agent_uses_default PASSED                                                 [  9%]
tests/test_ai_skills.py::TestGetSkillsDir::test_all_configured_agents_resolve PASSED                                              [ 10%]
tests/test_ai_skills.py::TestKimiLegacySkillMigration::test_migrates_legacy_dotted_skill_directory PASSED                         [ 11%]
tests/test_ai_skills.py::TestKimiLegacySkillMigration::test_removes_legacy_dir_when_hyphenated_target_exists_with_same_content PASSED [ 12%]
tests/test_ai_skills.py::TestKimiLegacySkillMigration::test_keeps_legacy_dir_when_hyphenated_target_differs PASSED                [ 13%]
tests/test_ai_skills.py::TestKimiLegacySkillMigration::test_keeps_legacy_dir_when_matching_target_but_extra_files_exist PASSED    [ 14%]
tests/test_ai_skills.py::TestInstallAiSkills::test_skills_installed_with_correct_structure PASSED                                 [ 15%]
tests/test_ai_skills.py::TestInstallAiSkills::test_generated_skill_has_parseable_yaml PASSED                                      [ 16%]
tests/test_ai_skills.py::TestInstallAiSkills::test_empty_yaml_frontmatter PASSED                                                  [ 17%]
tests/test_ai_skills.py::TestInstallAiSkills::test_enhanced_descriptions_used_when_available PASSED                               [ 18%]
tests/test_ai_skills.py::TestInstallAiSkills::test_template_without_frontmatter PASSED                                            [ 19%]
tests/test_ai_skills.py::TestInstallAiSkills::test_missing_templates_directory PASSED                                             [ 20%]
tests/test_ai_skills.py::TestInstallAiSkills::test_empty_templates_directory PASSED                                               [ 21%]
tests/test_ai_skills.py::TestInstallAiSkills::test_malformed_yaml_frontmatter PASSED                                              [ 22%]
tests/test_ai_skills.py::TestInstallAiSkills::test_additive_does_not_overwrite_other_files PASSED                                 [ 23%]
tests/test_ai_skills.py::TestInstallAiSkills::test_return_value PASSED                                                            [ 24%]
tests/test_ai_skills.py::TestInstallAiSkills::test_return_false_when_no_templates PASSED                                          [ 25%]
tests/test_ai_skills.py::TestInstallAiSkills::test_non_md_commands_dir_falls_back PASSED                                          [ 26%]
tests/test_ai_skills.py::TestInstallAiSkills::test_qwen_md_commands_dir_installs_skills PASSED                                    [ 27%]
tests/test_ai_skills.py::TestInstallAiSkills::test_pi_prompt_dir_installs_skills PASSED                                           [ 28%]
tests/test_ai_skills.py::TestInstallAiSkills::test_skills_install_for_all_agents[copilot] PASSED                                  [ 29%]
tests/test_ai_skills.py::TestInstallAiSkills::test_skills_install_for_all_agents[claude] PASSED                                   [ 30%]
tests/test_ai_skills.py::TestInstallAiSkills::test_skills_install_for_all_agents[gemini] PASSED                                   [ 31%]
tests/test_ai_skills.py::TestInstallAiSkills::test_skills_install_for_all_agents[cursor-agent] PASSED                             [ 32%]
tests/test_ai_skills.py::TestInstallAiSkills::test_skills_install_for_all_agents[qwen] PASSED                                     [ 33%]
tests/test_ai_skills.py::TestInstallAiSkills::test_skills_install_for_all_agents[opencode] PASSED                                 [ 34%]
tests/test_ai_skills.py::TestInstallAiSkills::test_skills_install_for_all_agents[codex] PASSED                                    [ 35%]
tests/test_ai_skills.py::TestInstallAiSkills::test_skills_install_for_all_agents[windsurf] PASSED                                 [ 36%]
tests/test_ai_skills.py::TestInstallAiSkills::test_skills_install_for_all_agents[junie] PASSED                                    [ 37%]
tests/test_ai_skills.py::TestInstallAiSkills::test_skills_install_for_all_agents[kilocode] PASSED                                 [ 38%]
tests/test_ai_skills.py::TestInstallAiSkills::test_skills_install_for_all_agents[auggie] PASSED                                   [ 39%]
tests/test_ai_skills.py::TestInstallAiSkills::test_skills_install_for_all_agents[codebuddy] PASSED                                [ 40%]
tests/test_ai_skills.py::TestInstallAiSkills::test_skills_install_for_all_agents[qodercli] PASSED                                 [ 41%]
tests/test_ai_skills.py::TestInstallAiSkills::test_skills_install_for_all_agents[roo] PASSED                                      [ 42%]
tests/test_ai_skills.py::TestInstallAiSkills::test_skills_install_for_all_agents[kiro-cli] PASSED                                 [ 43%]
tests/test_ai_skills.py::TestInstallAiSkills::test_skills_install_for_all_agents[amp] PASSED                                      [ 44%]
tests/test_ai_skills.py::TestInstallAiSkills::test_skills_install_for_all_agents[shai] PASSED                                     [ 45%]
tests/test_ai_skills.py::TestInstallAiSkills::test_skills_install_for_all_agents[tabnine] PASSED                                  [ 46%]
tests/test_ai_skills.py::TestInstallAiSkills::test_skills_install_for_all_agents[agy] PASSED                                      [ 47%]
tests/test_ai_skills.py::TestInstallAiSkills::test_skills_install_for_all_agents[bob] PASSED                                      [ 48%]
tests/test_ai_skills.py::TestInstallAiSkills::test_skills_install_for_all_agents[vibe] PASSED                                     [ 50%]
tests/test_ai_skills.py::TestInstallAiSkills::test_skills_install_for_all_agents[kimi] PASSED                                     [ 51%]
tests/test_ai_skills.py::TestInstallAiSkills::test_skills_install_for_all_agents[trae] PASSED                                     [ 52%]
tests/test_ai_skills.py::TestInstallAiSkills::test_skills_install_for_all_agents[pi] PASSED                                       [ 53%]
tests/test_ai_skills.py::TestInstallAiSkills::test_skills_install_for_all_agents[iflow] PASSED                                    [ 54%]
tests/test_ai_skills.py::TestInstallAiSkills::test_copilot_ignores_non_speckit_agents PASSED                                      [ 55%]
tests/test_ai_skills.py::TestInstallAiSkills::test_non_speckit_commands_ignored_for_all_agents[claude-review.md] PASSED           [ 56%]
tests/test_ai_skills.py::TestInstallAiSkills::test_non_speckit_commands_ignored_for_all_agents[cursor-agent-deploy.md] PASSED     [ 57%]
tests/test_ai_skills.py::TestInstallAiSkills::test_non_speckit_commands_ignored_for_all_agents[qwen-my-workflow.md] PASSED        [ 58%]
tests/test_ai_skills.py::TestInstallAiSkills::test_copilot_fallback_when_only_non_speckit_agents PASSED                           [ 59%]
tests/test_ai_skills.py::TestInstallAiSkills::test_fallback_when_only_non_speckit_commands[claude] PASSED                         [ 60%]
tests/test_ai_skills.py::TestInstallAiSkills::test_fallback_when_only_non_speckit_commands[cursor-agent] PASSED                   [ 61%]
tests/test_ai_skills.py::TestInstallAiSkills::test_fallback_when_only_non_speckit_commands[qwen] PASSED                           [ 62%]
tests/test_ai_skills.py::TestCommandCoexistence::test_existing_commands_preserved_claude PASSED                                   [ 63%]
tests/test_ai_skills.py::TestCommandCoexistence::test_existing_commands_preserved_gemini PASSED                                   [ 64%]
tests/test_ai_skills.py::TestCommandCoexistence::test_existing_commands_preserved_qwen PASSED                                     [ 65%]
tests/test_ai_skills.py::TestCommandCoexistence::test_commands_dir_not_removed PASSED                                             [ 66%]
tests/test_ai_skills.py::TestCommandCoexistence::test_no_commands_dir_no_error PASSED                                             [ 67%]
tests/test_ai_skills.py::TestNewProjectCommandSkip::test_init_claude_creates_root_CLAUDE_md PASSED                                [ 68%]
tests/test_ai_skills.py::TestNewProjectCommandSkip::test_new_project_commands_removed_after_skills_succeed PASSED                 [ 69%]
tests/test_ai_skills.py::TestNewProjectCommandSkip::test_new_project_nonstandard_commands_subdir_removed_after_skills_succeed PASSED [ 70%]
tests/test_ai_skills.py::TestNewProjectCommandSkip::test_codex_native_skills_preserved_without_conversion PASSED                  [ 71%]
tests/test_ai_skills.py::TestNewProjectCommandSkip::test_codex_native_skills_missing_falls_back_then_fails_cleanly PASSED         [ 72%]
tests/test_ai_skills.py::TestNewProjectCommandSkip::test_codex_native_skills_ignores_non_speckit_skill_dirs PASSED                [ 73%]
tests/test_ai_skills.py::TestNewProjectCommandSkip::test_kimi_legacy_migration_runs_without_ai_skills_flag PASSED                 [ 74%]
tests/test_ai_skills.py::TestNewProjectCommandSkip::test_codex_ai_skills_here_mode_preserves_existing_codex_dir PASSED            [ 75%]
tests/test_ai_skills.py::TestNewProjectCommandSkip::test_codex_ai_skills_fresh_dir_does_not_create_codex_dir PASSED               [ 76%]
tests/test_ai_skills.py::TestNewProjectCommandSkip::test_download_and_extract_template_blocks_zip_path_traversal[False] PASSED    [ 77%]
tests/test_ai_skills.py::TestNewProjectCommandSkip::test_download_and_extract_template_blocks_zip_path_traversal[True] PASSED     [ 78%]
tests/test_ai_skills.py::TestNewProjectCommandSkip::test_commands_preserved_when_skills_fail PASSED                               [ 79%]
tests/test_ai_skills.py::TestNewProjectCommandSkip::test_here_mode_commands_preserved PASSED                                      [ 80%]
tests/test_ai_skills.py::TestSkipIfExists::test_existing_skill_not_overwritten PASSED                                             [ 81%]
tests/test_ai_skills.py::TestSkipIfExists::test_fresh_install_writes_all_skills PASSED                                            [ 82%]
tests/test_ai_skills.py::TestSkipIfExists::test_existing_skill_overwritten_when_enabled PASSED                                    [ 83%]
tests/test_ai_skills.py::TestSkillDescriptions::test_all_known_commands_have_descriptions PASSED                                  [ 84%]
tests/test_ai_skills.py::TestCliValidation::test_ai_skills_without_ai_fails PASSED                                                [ 85%]
tests/test_ai_skills.py::TestCliValidation::test_ai_skills_without_ai_shows_usage PASSED                                          [ 86%]
tests/test_ai_skills.py::TestCliValidation::test_agy_without_ai_skills_fails PASSED                                               [ 87%]
tests/test_ai_skills.py::TestCliValidation::test_codex_without_ai_skills_fails PASSED                                             [ 88%]
tests/test_ai_skills.py::TestCliValidation::test_interactive_agy_without_ai_skills_prompts_skills PASSED                          [ 89%]
tests/test_ai_skills.py::TestCliValidation::test_interactive_codex_without_ai_skills_enables_skills PASSED                        [ 90%]
tests/test_ai_skills.py::TestCliValidation::test_kimi_next_steps_show_skill_invocation PASSED                                     [ 91%]
tests/test_ai_skills.py::TestCliValidation::test_ai_skills_flag_appears_in_help PASSED                                            [ 92%]
tests/test_ai_skills.py::TestCliValidation::test_kiro_alias_normalized_to_kiro_cli PASSED                                         [ 93%]
tests/test_ai_skills.py::TestCliValidation::test_q_removed_from_agent_config PASSED                                               [ 94%]
tests/test_ai_skills.py::TestParameterOrderingIssue::test_ai_flag_consuming_here_flag PASSED                                      [ 95%]
tests/test_ai_skills.py::TestParameterOrderingIssue::test_ai_flag_consuming_ai_skills_flag PASSED                                 [ 96%]
tests/test_ai_skills.py::TestParameterOrderingIssue::test_error_message_provides_hint PASSED                                      [ 97%]
tests/test_ai_skills.py::TestParameterOrderingIssue::test_error_message_lists_available_agents PASSED                             [ 98%]
tests/test_ai_skills.py::TestParameterOrderingIssue::test_ai_commands_dir_consuming_flag PASSED                                   [100%]

========================================================== 98 passed in 0.64s ===========================================================
  • Tested with a sample project (if applicable)

Here is the output

(specify-cli) arungupta@Mac spec-kit % specify init /tmp/speckit-test2 --ai claude
                                          ███████╗██████╗ ███████╗ ██████╗██╗███████╗██╗   ██╗                                           
                                          ██╔════╝██╔══██╗██╔════╝██╔════╝██║██╔════╝╚██╗ ██╔╝                                           
                                          ███████╗██████╔╝█████╗  ██║     ██║█████╗   ╚████╔╝                                            
                                          ╚════██║██╔═══╝ ██╔══╝  ██║     ██║██╔══╝    ╚██╔╝                                             
                                          ███████║██║     ███████╗╚██████╗██║██║        ██║                                              
                                          ╚══════╝╚═╝     ╚══════╝ ╚═════╝╚═╝╚═╝        ╚═╝                                              
                                                                                                                                         
                                            GitHub Spec Kit - Spec-Driven Development Toolkit                                            

╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│                                                                                                                                       │
│  Specify Project Setup                                                                                                                │
│                                                                                                                                       │
│  Project         speckit-test2                                                                                                        │
│  Working Path    /Users/arungupta/workspaces/spec-kit                                                                                 │
│  Target Path     /private/tmp/speckit-test2                                                                                           │
│                                                                                                                                       │
╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯

Selected AI assistant: claude
Selected script type: sh
Initialize Specify Project
├── ● Check required tools (ok)
├── ● Select AI assistant (claude)
├── ● Select script type (sh)
├── ● Fetch latest release (release v0.4.3 (64,591 bytes))
├── ● Download template (spec-kit-template-claude-sh-v0.4.3.zip)
├── ● Extract template
├── ● Archive contents (26 entries)
├── ● Extraction summary (2 top-level items)
├── ● Ensure scripts executable (5 updated)
├── ● Constitution setup (copied from template)
├── ● Claude Code role file (created)
├── ● Cleanup
├── ● Initialize git repository (initialized)
└── ● Finalize (project ready)

Project ready.

╭──────────────────────────────────────────────────────── Agent Folder Security ────────────────────────────────────────────────────────╮
│                                                                                                                                       │
│  Some agents may store credentials, auth tokens, or other identifying and private artifacts in the agent folder within your project.  │
│  Consider adding .claude/ (or parts of it) to .gitignore to prevent accidental credential leakage.                                    │
│                                                                                                                                       │
╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯

╭───────────────────────────────────────────────────────────── Next Steps ──────────────────────────────────────────────────────────────╮
│                                                                                                                                       │
│  1. Go to the project folder: cd /tmp/speckit-test2                                                                                   │
│  2. Start using slash commands with your AI agent:                                                                                    │
│     2.1 /speckit.constitution - Establish project principles                                                                          │
│     2.2 /speckit.specify - Create baseline specification                                                                              │
│     2.3 /speckit.plan - Create implementation plan                                                                                    │
│     2.4 /speckit.tasks - Generate actionable tasks                                                                                    │
│     2.5 /speckit.implement - Execute implementation                                                                                   │
│                                                                                                                                       │
╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯

╭──────────────────────────────────────────────────────── Enhancement Commands ─────────────────────────────────────────────────────────╮
│                                                                                                                                       │
│  Optional commands that you can use for your specs (improve quality & confidence)                                                     │
│                                                                                                                                       │
│  ○ /speckit.clarify (optional) - Ask structured questions to de-risk ambiguous areas before planning (run before /speckit.plan if     │
│  used)                                                                                                                                │
│  ○ /speckit.analyze (optional) - Cross-artifact consistency & alignment report (after /speckit.tasks, before /speckit.implement)      │
│  ○ /speckit.checklist (optional) - Generate quality checklists to validate requirements completeness, clarity, and consistency        │
│  (after /speckit.plan)                                                                                                                │
│                                                                                                                                       │
╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
(specify-cli) arungupta@Mac spec-kit %

AI Disclosure

  • I did not use AI assistance for this contribution
  • I did use AI assistance (describe below)

I used Cursor to understand the codebase and generate the code for this particular fix. I read through the code 3x to ensure it's aligned with the rest of the codebase. I own the responsibility for this fix.

Ensure `specify init --ai claude` creates a minimal root CLAUDE.md pointing to `.specify/memory/constitution.md`, and add a regression test for issue github#1983.

Made-with: Cursor
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Ensures specify init --ai claude creates a minimal root CLAUDE.md so Claude Code automatically picks up Spec Kit guidance by pointing to .specify/memory/constitution.md.

Changes:

  • Added ensure_claude_md() helper to generate a root CLAUDE.md for Claude projects (preserving any existing file).
  • Wired Claude-specific CLAUDE.md generation into the init() flow and step tracker.
  • Added an end-to-end CLI test asserting CLAUDE.md is created and contains expected guidance.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

File Description
src/specify_cli/__init__.py Adds ensure_claude_md() and calls it during init() for --ai claude.
tests/test_ai_skills.py Adds a CLI test to verify CLAUDE.md is created during offline init.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +1477 to +1488
content = (
"## Claude's Role\n"
"Read `.specify/memory/constitution.md` first. It is the authoritative source of truth for this project. "
"Everything in it is non-negotiable.\n\n"
"## SpecKit Commands\n"
"- `/speckit.specify` — generate spec\n"
"- `/speckit.plan` — generate plan\n"
"- `/speckit.tasks` — generate task list\n"
"- `/speckit.implement` — execute plan\n\n"
"## On Ambiguity\n"
"If a spec is missing, incomplete, or conflicts with the constitution — stop and ask. "
"Do not infer. Do not proceed.\n\n"
Copy link

Copilot AI Mar 26, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ensure_claude_md() will create a root CLAUDE.md that instructs Claude to read .specify/memory/constitution.md even when that file does not exist (e.g., when ensure_constitution_from_template() failed because the template was missing). Consider gating CLAUDE.md creation on the constitution file existing (or on the template being present), and mark the tracker step as error/skipped otherwise to avoid generating misleading guidance.

Copilot uses AI. Check for mistakes.
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated

Comment on lines +706 to +719
result = runner.invoke(
app,
[
"init",
str(target),
"--ai",
"claude",
"--offline",
"--ignore-agent-tools",
"--no-git",
"--script",
"sh",
],
)
Copy link

Copilot AI Mar 26, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test runs the full specify init --offline scaffolding path (requiring external bash + zip) instead of using the class’s existing approach of patching download_and_extract_template/scaffolding helpers. That makes the test slower and potentially skipped/flaky depending on the environment, reducing the chance the behavior is exercised in CI. Recommend patching the extraction/scaffold steps (and creating the minimal .specify/... structure needed) so the test is deterministic and does not depend on system tools.

Suggested change
result = runner.invoke(
app,
[
"init",
str(target),
"--ai",
"claude",
"--offline",
"--ignore-agent-tools",
"--no-git",
"--script",
"sh",
],
)
with patch.object(specify_cli, "download_and_extract_template", self._fake_extract):
result = runner.invoke(
app,
[
"init",
str(target),
"--ai",
"claude",
"--offline",
"--ignore-agent-tools",
"--no-git",
"--script",
"sh",
],
)

Copilot uses AI. Check for mistakes.
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated

generate CLAUDE.md only when `.specify/memory/constitution.md` exists to avoid misleading guidance, and make the regression test deterministic by patching init scaffolding.

Made-with: Cursor
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: specify init --ai claude does not generate CLAUDE.md

3 participants