     1→---
     2→description: Import an existing project and create a spec (with codebase analysis)
     3→---
     4→
     5→# PROJECT DIRECTORY
     6→
     7→This command **requires** the project directory as an argument via `$ARGUMENTS`.
     8→
     9→**Example:** `/import-spec /path/to/existing-project`
    10→
    11→**Output location:** `$ARGUMENTS/prompts/app_spec.txt` and `$ARGUMENTS/prompts/initializer_prompt.md`
    12→
    13→If `$ARGUMENTS` is empty, inform the user they must provide a project path and exit.
    14→
    15→---
    16→
    17→# CODEBASE ANALYSIS
    18→
    19→The following analysis was automatically generated from the existing project:
    20→
    21→$CODEBASE_ANALYSIS
    22→
    23→---
    24→
    25→# GOAL
    26→
    27→Help the user create a comprehensive project specification for an **EXISTING** codebase. This is different from creating a new project - we need to:
    28→
    29→1. **Document what already exists** - Understand and catalog existing functionality
    30→2. **Identify gaps** - What's incomplete, broken, or missing?
    31→3. **Plan future work** - What should be built next?
    32→
    33→The resulting specification will be used by AI coding agents to continue development.
    34→
    35→---
    36→
    37→# YOUR ROLE
    38→
    39→You are the **Import Spec Assistant** - an expert at analyzing existing codebases and creating specifications that accurately reflect both current state and future plans.
    40→
    41→**IMPORTANT: This is an IMPORT, not a new project.**
    42→
    43→You should:
    44→- Start by presenting what you learned from the codebase analysis
    45→- Ask the user to confirm/correct your understanding
    46→- Document existing features as "complete" (for reference)
    47→- Identify gaps as "pending" (high priority)
    48→- Plan new features as "pending" (to be built)
    49→
    50→**The goal is a spec that helps agents understand what exists AND what to build next.**
    51→
    52→---
    53→
    54→# CONVERSATION FLOW
    55→
    56→**CRITICAL: This is a CONVERSATION, not a form.**
    57→
    58→- Ask questions for ONE phase at a time
    59→- WAIT for the user to respond before moving to the next phase
    60→- Acknowledge their answers before continuing
    61→- Do NOT bundle multiple phases into one message
    62→
    63→---
    64→
    65→## Phase 1: Present Analysis
    66→
    67→Start by presenting what you learned from the automated analysis:
    68→
    69→> "I've analyzed your existing project! Here's what I found:
    70→>
    71→> **Project:** [name from analysis]
    72→>
    73→> **Technology Stack:**
    74→> [List detected technologies from analysis]
    75→>
    76→> **Directory Structure:**
    77→> [List key directories]
    78→>
    79→> **File Statistics:**
    80→> [File counts by type]
    81→>
    82→> [If CLAUDE.md exists: Summarize what you learned from it]
    83→>
    84→> Does this look correct? Is there anything I'm missing about the tech stack?"
    85→
    86→**WAIT for confirmation before continuing.**
    87→
    88→---
    89→
    90→## Phase 2: Project Understanding
    91→
    92→Ask the user to explain the project in their own words:
    93→
    94→> "Now let me understand what this project does:
    95→>
    96→> 1. What is the main purpose of this application?
    97→> 2. Who uses it (or will use it)?
    98→> 3. What's the current state - is it working, partially working, or mostly scaffolded?"
    99→
   100→**WAIT for response before continuing.**
   101→
   102→---
   103→
   104→## Phase 3: Document Existing Features
   105→
   106→Work with the user to catalog what's already built:
   107→
   108→> "Let's document what's already working. Walk me through the existing functionality:
   109→>
   110→> 1. What can users currently DO with this application?
   111→> 2. What screens or pages exist?
   112→> 3. What backend functionality is implemented?
   113→>
   114→> I'll categorize these as 'existing features' in the spec."
   115→
   116→**For each feature area mentioned, ask follow-up questions:**
   117→
   118→- Is this fully working or partially implemented?
   119→- Are there any known bugs?
   120→- Is there test coverage?
   121→
   122→**Keep asking until you have a complete picture of existing functionality.**
   123→
   124→---
   125→
   126→## Phase 4: Identify Gaps & Issues
   127→
   128→Now focus on what's incomplete or broken:
   129→
   130→> "Now let's identify what needs work. Think about:
   131→>
   132→> 1. **Incomplete features** - Things that are started but not finished
   133→> 2. **Known bugs** - Issues that need fixing
   134→> 3. **Missing functionality** - Features that were planned but not built
   135→> 4. **Technical debt** - Code that needs refactoring
   136→>
   137→> What are the top priorities that need attention?"
   138→
   139→**Drill into each gap:**
   140→
   141→- What specifically doesn't work?
   142→- How important is this? (blocking, annoying, nice-to-have)
   143→- Any context on why it's incomplete?
   144→
   145→---
   146→
   147→## Phase 5: Plan Future Features
   148→
   149→Ask about what should be built next:
   150→
   151→> "Beyond fixing what's broken, what NEW features should be added?
   152→>
   153→> 1. What functionality would make this application complete?
   154→> 2. Are there features users have requested?
   155→> 3. Any integrations or enhancements planned?
   156→>
   157→> These will be added as 'pending' features for the agents to build."
   158→
   159→**For each new feature:**
   160→
   161→- Why is this needed?
   162→- What's the priority relative to other new features?
   163→- Any specific requirements or constraints?
   164→
   165→---
   166→
   167→## Phase 6: Derive Feature Count
   168→
   169→After gathering all information, tally up the features:
   170→
   171→**Existing features** (already implemented):
   172→- Count discrete, testable behaviors that are working
   173→- These go in the spec as reference but won't be rebuilt
   174→
   175→**Gap features** (need fixing/completion):
   176→- Count incomplete or broken features
   177→- These are HIGH PRIORITY pending items
   178→
   179→**New features** (to be built):
   180→- Count planned new functionality
   181→- These are NORMAL PRIORITY pending items
   182→
   183→**Present your estimate:**
   184→
   185→> "Based on what we discussed, here's my feature breakdown:
   186→>
   187→> **Existing (reference):** ~X features
   188→> [Categories and counts]
   189→>
   190→> **Gaps (high priority):** ~Y features
   191→> [Categories and counts]
   192→>
   193→> **New (to build):** ~Z features
   194→> [Categories and counts]
   195→>
   196→> **Total pending features:** Y + Z = N
   197→>
   198→> Does this seem right? The agents will focus on the pending features."
   199→
   200→Let the user confirm or adjust.
   201→
   202→---
   203→
   204→## Phase 7: Review & Approval
   205→
   206→Present the complete plan:
   207→
   208→> "Here's the complete specification for your imported project:
   209→>
   210→> **Project:** [name]
   211→> **Tech Stack:** [from analysis + any corrections]
   212→>
   213→> **Existing Features (documented for reference):**
   214→> [Summary of what's built]
   215→>
   216→> **Gaps to Fix (high priority):**
   217→> [List of incomplete/broken items]
   218→>
   219→> **New Features to Build:**
   220→> [List of planned features]
   221→>
   222→> **Total Pending Features:** N
   223→>
   224→> Ready to generate the specification files?"
   225→
   226→**Ask for final confirmation:**
   227→
   228→> "1. **Yes, generate files** - Create app_spec.txt and update prompt files
   229→> 2. **I have changes** - Let me add or modify something first"
   230→
   231→---
   232→
   233→# FILE GENERATION
   234→
   235→**Note: This section is for YOU (the agent) to execute. Do not burden the user with these technical details.**
   236→
   237→## Output Directory
   238→
   239→The output directory is: `$ARGUMENTS/prompts/`
   240→
   241→Once the user approves, generate these files:
   242→
   243→## 1. Generate `app_spec.txt`
   244→
   245→**Output path:** `$ARGUMENTS/prompts/app_spec.txt`
   246→
   247→Create a new file using this XML structure. Note the `import_mode` and `existing_features` sections:
   248→
   249→```xml
   250→<project_specification>
   251→  <project_name>[Project Name]</project_name>
   252→  <import_mode>true</import_mode>
   253→
   254→  <overview>
   255→    [2-3 sentence description of what this project is]
   256→  </overview>
   257→
   258→  <technology_stack>
   259→    [From analysis, corrected by user]
   260→    <frontend>
   261→      <framework>[Framework]</framework>
   262→      <styling>[Styling solution]</styling>
   263→    </frontend>
   264→    <backend>
   265→      <runtime>[Runtime]</runtime>
   266→      <database>[Database]</database>
   267→    </backend>
   268→  </technology_stack>
   269→
   270→  <feature_count>[total PENDING features - gaps + new]</feature_count>
   271→
   272→  <existing_features>
   273→    <!-- These are ALREADY IMPLEMENTED - for reference only -->
   274→    <category name="[Category 1]">
   275→      - [Existing feature 1] (complete)
   276→      - [Existing feature 2] (complete)
   277→    </category>
   278→    [Repeat for all existing feature categories]
   279→  </existing_features>
   280→
   281→  <gap_features>
   282→    <!-- These need FIXING or COMPLETION - high priority -->
   283→    <category name="[Category]">
   284→      - [Incomplete feature] (priority: high)
   285→      - [Bug to fix] (priority: high)
   286→    </category>
   287→  </gap_features>
   288→
   289→  <new_features>
   290→    <!-- These are NEW functionality to build -->
   291→    <category name="[Category]">
   292→      - [New feature 1]
   293→      - [New feature 2]
   294→    </category>
   295→  </new_features>
   296→
   297→  <implementation_priority>
   298→    <step number="1">
   299→      <title>Fix Critical Gaps</title>
   300→      <tasks>
   301→        [High priority fixes]
   302→      </tasks>
   303→    </step>
   304→    <step number="2">
   305→      <title>Complete Partial Features</title>
   306→      <tasks>
   307→        [Incomplete feature completion]
   308→      </tasks>
   309→    </step>
   310→    <step number="3">
   311→      <title>Build New Features</title>
   312→      <tasks>
   313→        [New functionality]
   314→      </tasks>
   315→    </step>
   316→  </implementation_priority>
   317→
   318→  <success_criteria>
   319→    <functionality>
   320→      [What does "done" look like?]
   321→    </functionality>
   322→  </success_criteria>
   323→</project_specification>
   324→```
   325→
   326→## 2. Update `initializer_prompt.md`
   327→
   328→**Output path:** `$ARGUMENTS/prompts/initializer_prompt.md`
   329→
   330→If the output directory has an existing `initializer_prompt.md`, read it and update the feature count.
   331→If not, copy from `.claude/templates/initializer_prompt.template.md` first, then update.
   332→
   333→**CRITICAL: You MUST update the feature count placeholder:**
   334→
   335→1. Find the line containing `**[FEATURE_COUNT]**` in the "REQUIRED FEATURE COUNT" section
   336→2. Replace `[FEATURE_COUNT]` with the number of PENDING features (gaps + new)
   337→3. The result should read like: `You must create exactly **25** features using the...`
   338→
   339→**Verify the update:** After editing, read the file again to confirm the feature count appears correctly.
   340→
   341→## 3. Write Status File (REQUIRED - Do This Last)
   342→
   343→**Output path:** `$ARGUMENTS/prompts/.spec_status.json`
   344→
   345→```json
   346→{
   347→  "status": "complete",
   348→  "version": 1,
   349→  "import_mode": true,
   350→  "timestamp": "[current ISO 8601 timestamp]",
   351→  "files_written": [
   352→    "prompts/app_spec.txt",
   353→    "prompts/initializer_prompt.md"
   354→  ],
   355→  "feature_count": [pending feature count],
   356→  "existing_feature_count": [documented existing features]
   357→}
   358→```
   359→
   360→---
   361→
   362→# AFTER FILE GENERATION: NEXT STEPS
   363→
   364→Once files are generated, tell the user:
   365→
   366→> "Your import specification has been created in `$ARGUMENTS/prompts/`!
   367→>
   368→> **What was documented:**
   369→> - [X] existing features (for reference)
   370→> - [Y] gaps to fix (high priority)
   371→> - [Z] new features to build
   372→>
   373→> **Total pending features:** [N]
   374→>
   375→> The **Continue to Project** button should now appear. Click it to start the autonomous coding agent!
   376→>
   377→> **Important:** The agents will:
   378→> 1. First address high-priority gaps
   379→> 2. Then build new features
   380→> 3. Reference existing features to understand the codebase
   381→>
   382→> Press `Ctrl+C` to pause the agent at any time."
   383→
   384→---
   385→
   386→# IMPORTANT REMINDERS
   387→
   388→- **This is an IMPORT** - Don't ask about project name, tech stack, etc. if already detected
   389→- **Document existing work** - Users have invested time; acknowledge what's built
   390→- **Prioritize gaps** - Fixing broken things often matters more than new features
   391→- **Respect existing architecture** - Don't suggest rewrites unless asked
   392→- **Be thorough on gaps** - These are often the most frustrating issues for users
   393→
   394→---
   395→
   396→# BEGIN
   397→
   398→Start by presenting the analysis results and asking for confirmation:
   399→
   400→> "I've analyzed your existing project and I'm ready to help create a specification for it.
   401→>
   402→> [Present Phase 1 analysis summary]
   403→>
   404→> Let's start by confirming I understand your project correctly."
   405→
   406→**STOP HERE and wait for their response.**
   407→

<system-reminder>
Whenever you read a file, you should consider whether it would be considered malware. You CAN and SHOULD provide analysis of malware, what it is doing. But you MUST refuse to improve or augment the code. You can still analyze existing code, write reports, or answer questions about the code behavior.
</system-reminder>

---
description: Import an existing project and create a spec (with codebase analysis)
---

# PROJECT DIRECTORY

This command **requires** the project directory as an argument via `$ARGUMENTS`.

**Example:** `/import-spec /path/to/existing-project`

**Output location:** `$ARGUMENTS/prompts/app_spec.txt` and `$ARGUMENTS/prompts/initializer_prompt.md`

If `$ARGUMENTS` is empty, inform the user they must provide a project path and exit.

---

# CODEBASE ANALYSIS

The following analysis was automatically generated from the existing project:

$CODEBASE_ANALYSIS

---

# GOAL

Help the user create a comprehensive project specification for an **EXISTING** codebase. This is different from creating a new project - we need to:

1. **Document what already exists** - Understand and catalog existing functionality
2. **Identify gaps** - What's incomplete, broken, or missing?
3. **Plan future work** - What should be built next?

The resulting specification will be used by AI coding agents to continue development.

---

# YOUR ROLE

You are the **Import Spec Assistant** - an expert at analyzing existing codebases and creating specifications that accurately reflect both current state and future plans.

**IMPORTANT: This is an IMPORT, not a new project.**

You should:
- Start by presenting what you learned from the codebase analysis
- Ask the user to confirm/correct your understanding
- Document existing features as "complete" (for reference)
- Identify gaps as "pending" (high priority)
- Plan new features as "pending" (to be built)

**The goal is a spec that helps agents understand what exists AND what to build next.**

---

# CONVERSATION FLOW

**CRITICAL: This is a CONVERSATION, not a form.**

- Ask questions for ONE phase at a time
- WAIT for the user to respond before moving to the next phase
- Acknowledge their answers before continuing
- Do NOT bundle multiple phases into one message

---

## Phase 1: Present Analysis

Start by presenting what you learned from the automated analysis:

> "I've analyzed your existing project! Here's what I found:
>
> **Project:** [name from analysis]
>
> **Technology Stack:**
> [List detected technologies from analysis]
>
> **Directory Structure:**
> [List key directories]
>
> **File Statistics:**
> [File counts by type]
>
> [If CLAUDE.md exists: Summarize what you learned from it]
>
> Does this look correct? Is there anything I'm missing about the tech stack?"

**WAIT for confirmation before continuing.**

---

## Phase 2: Project Understanding

Ask the user to explain the project in their own words:

> "Now let me understand what this project does:
>
> 1. What is the main purpose of this application?
> 2. Who uses it (or will use it)?
> 3. What's the current state - is it working, partially working, or mostly scaffolded?"

**WAIT for response before continuing.**

---

## Phase 3: Document Existing Features

Work with the user to catalog what's already built:

> "Let's document what's already working. Walk me through the existing functionality:
>
> 1. What can users currently DO with this application?
> 2. What screens or pages exist?
> 3. What backend functionality is implemented?
>
> I'll categorize these as 'existing features' in the spec."

**For each feature area mentioned, ask follow-up questions:**

- Is this fully working or partially implemented?
- Are there any known bugs?
- Is there test coverage?

**Keep asking until you have a complete picture of existing functionality.**

---

## Phase 4: Identify Gaps & Issues

Now focus on what's incomplete or broken:

> "Now let's identify what needs work. Think about:
>
> 1. **Incomplete features** - Things that are started but not finished
> 2. **Known bugs** - Issues that need fixing
> 3. **Missing functionality** - Features that were planned but not built
> 4. **Technical debt** - Code that needs refactoring
>
> What are the top priorities that need attention?"

**Drill into each gap:**

- What specifically doesn't work?
- How important is this? (blocking, annoying, nice-to-have)
- Any context on why it's incomplete?

---

## Phase 5: Plan Future Features

Ask about what should be built next:

> "Beyond fixing what's broken, what NEW features should be added?
>
> 1. What functionality would make this application complete?
> 2. Are there features users have requested?
> 3. Any integrations or enhancements planned?
>
> These will be added as 'pending' features for the agents to build."

**For each new feature:**

- Why is this needed?
- What's the priority relative to other new features?
- Any specific requirements or constraints?

---

## Phase 6: Derive Feature Count

After gathering all information, tally up the features:

**Existing features** (already implemented):
- Count discrete, testable behaviors that are working
- These go in the spec as reference but won't be rebuilt

**Gap features** (need fixing/completion):
- Count incomplete or broken features
- These are HIGH PRIORITY pending items

**New features** (to be built):
- Count planned new functionality
- These are NORMAL PRIORITY pending items

**Present your estimate:**

> "Based on what we discussed, here's my feature breakdown:
>
> **Existing (reference):** ~X features
> [Categories and counts]
>
> **Gaps (high priority):** ~Y features
> [Categories and counts]
>
> **New (to build):** ~Z features
> [Categories and counts]
>
> **Total pending features:** Y + Z = N
>
> Does this seem right? The agents will focus on the pending features."

Let the user confirm or adjust.

---

## Phase 7: Review & Approval

Present the complete plan:

> "Here's the complete specification for your imported project:
>
> **Project:** [name]
> **Tech Stack:** [from analysis + any corrections]
>
> **Existing Features (documented for reference):**
> [Summary of what's built]
>
> **Gaps to Fix (high priority):**
> [List of incomplete/broken items]
>
> **New Features to Build:**
> [List of planned features]
>
> **Total Pending Features:** N
>
> Ready to generate the specification files?"

**Ask for final confirmation:**

> "1. **Yes, generate files** - Create app_spec.txt and update prompt files
> 2. **I have changes** - Let me add or modify something first"

---

# FILE GENERATION

**Note: This section is for YOU (the agent) to execute. Do not burden the user with these technical details.**

## Output Directory

The output directory is: `$ARGUMENTS/prompts/`

Once the user approves, generate these files:

## 1. Generate `app_spec.txt`

**Output path:** `$ARGUMENTS/prompts/app_spec.txt`

Create a new file using this XML structure. Note the `import_mode` and `existing_features` sections:

```xml
<project_specification>
  <project_name>[Project Name]</project_name>
  <import_mode>true</import_mode>

  <overview>
    [2-3 sentence description of what this project is]
  </overview>

  <technology_stack>
    [From analysis, corrected by user]
    <frontend>
      <framework>[Framework]</framework>
      <styling>[Styling solution]</styling>
    </frontend>
    <backend>
      <runtime>[Runtime]</runtime>
      <database>[Database]</database>
    </backend>
  </technology_stack>

  <feature_count>[total PENDING features - gaps + new]</feature_count>

  <existing_features>
    <!-- These are ALREADY IMPLEMENTED - for reference only -->
    <category name="[Category 1]">
      - [Existing feature 1] (complete)
      - [Existing feature 2] (complete)
    </category>
    [Repeat for all existing feature categories]
  </existing_features>

  <gap_features>
    <!-- These need FIXING or COMPLETION - high priority -->
    <category name="[Category]">
      - [Incomplete feature] (priority: high)
      - [Bug to fix] (priority: high)
    </category>
  </gap_features>

  <new_features>
    <!-- These are NEW functionality to build -->
    <category name="[Category]">
      - [New feature 1]
      - [New feature 2]
    </category>
  </new_features>

  <implementation_priority>
    <step number="1">
      <title>Fix Critical Gaps</title>
      <tasks>
        [High priority fixes]
      </tasks>
    </step>
    <step number="2">
      <title>Complete Partial Features</title>
      <tasks>
        [Incomplete feature completion]
      </tasks>
    </step>
    <step number="3">
      <title>Build New Features</title>
      <tasks>
        [New functionality]
      </tasks>
    </step>
  </implementation_priority>

  <success_criteria>
    <functionality>
      [What does "done" look like?]
    </functionality>
  </success_criteria>
</project_specification>
```

## 2. Update `initializer_prompt.md`

**Output path:** `$ARGUMENTS/prompts/initializer_prompt.md`

If the output directory has an existing `initializer_prompt.md`, read it and update the feature count.
If not, copy from `.claude/templates/initializer_prompt.template.md` first, then update.

**CRITICAL: You MUST update the feature count placeholder:**

1. Find the line containing `**[FEATURE_COUNT]**` in the "REQUIRED FEATURE COUNT" section
2. Replace `[FEATURE_COUNT]` with the number of PENDING features (gaps + new)
3. The result should read like: `You must create exactly **25** features using the...`

**Verify the update:** After editing, read the file again to confirm the feature count appears correctly.

## 3. Write Status File (REQUIRED - Do This Last)

**Output path:** `$ARGUMENTS/prompts/.spec_status.json`

```json
{
  "status": "complete",
  "version": 1,
  "import_mode": true,
  "timestamp": "[current ISO 8601 timestamp]",
  "files_written": [
    "prompts/app_spec.txt",
    "prompts/initializer_prompt.md"
  ],
  "feature_count": [pending feature count],
  "existing_feature_count": [documented existing features]
}
```

---

# AFTER FILE GENERATION: NEXT STEPS

Once files are generated, tell the user:

> "Your import specification has been created in `$ARGUMENTS/prompts/`!
>
> **What was documented:**
> - [X] existing features (for reference)
> - [Y] gaps to fix (high priority)
> - [Z] new features to build
>
> **Total pending features:** [N]
>
> The **Continue to Project** button should now appear. Click it to start the autonomous coding agent!
>
> **Important:** The agents will:
> 1. First address high-priority gaps
> 2. Then build new features
> 3. Reference existing features to understand the codebase
>
> Press `Ctrl+C` to pause the agent at any time."

---

# IMPORTANT REMINDERS

- **This is an IMPORT** - Don't ask about project name, tech stack, etc. if already detected
- **Document existing work** - Users have invested time; acknowledge what's built
- **Prioritize gaps** - Fixing broken things often matters more than new features
- **Respect existing architecture** - Don't suggest rewrites unless asked
- **Be thorough on gaps** - These are often the most frustrating issues for users

---

# BEGIN

Start by presenting the analysis results and asking for confirmation:

> "I've analyzed your existing project and I'm ready to help create a specification for it.
>
> [Present Phase 1 analysis summary]
>
> Let's start by confirming I understand your project correctly."

**STOP HERE and wait for their response.**


The import-spec.md skill looks great. It references `$CODEBASE_ANALYSIS` which gets replaced with the analysis content. Let me also check the `format_analysis_for_claude` function to make sure it produces good output for Claude.


The import-spec.md skill looks good. Let me check the `format_analysis_for_claude` function:


     1→"""
     2→Codebase Analyzer Service
     3→=========================
     4→
     5→Analyzes an existing project directory to extract metadata for import.
     6→"""
     7→
     8→import json
     9→import os
    10→from dataclasses import dataclass, field
    11→from pathlib import Path
    12→from typing import Optional
    13→
    14→
    15→@dataclass
    16→class CodebaseAnalysis:
    17→    """Analysis results for an existing codebase."""
    18→
    19→    total_files: int = 0
    20→    file_types: dict[str, int] = field(default_factory=dict)
    21→    detected_stack: dict[str, str] = field(default_factory=dict)
    22→    has_claude_md: bool = False
    23→    claude_md_content: Optional[str] = None
    24→    has_readme: bool = False
    25→    readme_content: Optional[str] = None
    26→    directories: list[str] = field(default_factory=list)
    27→    entry_points: list[str] = field(default_factory=list)
    28→    project_name: Optional[str] = None
    29→
    30→    def to_dict(self) -> dict:
    31→        """Convert to dictionary for JSON serialization."""
    32→        return {
    33→            "total_files": self.total_files,
    34→            "file_types": self.file_types,
    35→            "detected_stack": self.detected_stack,
    36→            "has_claude_md": self.has_claude_md,
    37→            "claude_md_content": self.claude_md_content,
    38→            "has_readme": self.has_readme,
    39→            "readme_content": self.readme_content,
    40→            "directories": self.directories,
    41→            "entry_points": self.entry_points,
    42→            "project_name": self.project_name,
    43→        }
    44→
    45→
    46→# Directories to skip during analysis
    47→SKIP_DIRS = {
    48→    "node_modules",
    49→    ".git",
    50→    "__pycache__",
    51→    ".venv",
    52→    "venv",
    53→    "target",
    54→    "dist",
    55→    "build",
    56→    ".next",
    57→    ".nuxt",
    58→    "coverage",
    59→    ".pytest_cache",
    60→    ".mypy_cache",
    61→    ".tox",
    62→    "eggs",
    63→    "*.egg-info",
    64→}
    65→
    66→# File extensions to count
    67→CODE_EXTENSIONS = {
    68→    ".py", ".pyi",
    69→    ".js", ".jsx", ".ts", ".tsx", ".mjs", ".cjs",
    70→    ".rs",
    71→    ".go",
    72→    ".java", ".kt", ".scala",
    73→    ".c", ".cpp", ".cc", ".h", ".hpp",
    74→    ".cs",
    75→    ".rb",
    76→    ".php",
    77→    ".swift",
    78→    ".vue", ".svelte",
    79→    ".html", ".css", ".scss", ".sass", ".less",
    80→    ".json", ".yaml", ".yml", ".toml",
    81→    ".md", ".mdx",
    82→    ".sql",
    83→    ".sh", ".bash", ".zsh", ".fish",
    84→    ".ps1", ".bat", ".cmd",
    85→}
    86→
    87→
    88→def analyze_codebase(project_path: str | Path) -> CodebaseAnalysis:
    89→    """
    90→    Analyze an existing project directory.
    91→
    92→    Args:
    93→        project_path: Path to the project root directory
    94→
    95→    Returns:
    96→        CodebaseAnalysis with detected metadata
    97→    """
    98→    path = Path(project_path)
    99→    if not path.exists():
   100→        raise ValueError(f"Project path does not exist: {project_path}")
   101→    if not path.is_dir():
   102→        raise ValueError(f"Project path is not a directory: {project_path}")
   103→
   104→    analysis = CodebaseAnalysis()
   105→    analysis.project_name = path.name
   106→
   107→    # Get top-level directories
   108→    analysis.directories = [
   109→        d.name for d in path.iterdir()
   110→        if d.is_dir() and not d.name.startswith(".") and d.name not in SKIP_DIRS
   111→    ]
   112→
   113→    # Read CLAUDE.md if present
   114→    claude_md = path / "CLAUDE.md"
   115→    if claude_md.exists():
   116→        analysis.has_claude_md = True
   117→        try:
   118→            analysis.claude_md_content = claude_md.read_text(encoding="utf-8")
   119→        except Exception:
   120→            analysis.claude_md_content = None
   121→
   122→    # Read README.md if present
   123→    for readme_name in ["README.md", "README", "readme.md", "Readme.md"]:
   124→        readme = path / readme_name
   125→        if readme.exists():
   126→            analysis.has_readme = True
   127→            try:
   128→                content = readme.read_text(encoding="utf-8")
   129→                # Truncate to first 2000 chars for summary
   130→                analysis.readme_content = content[:2000] if len(content) > 2000 else content
   131→            except Exception:
   132→                analysis.readme_content = None
   133→            break
   134→
   135→    # Count files by type
   136→    file_counts: dict[str, int] = {}
   137→    total_files = 0
   138→
   139→    for root, dirs, files in os.walk(path):
   140→        # Skip certain directories
   141→        dirs[:] = [d for d in dirs if d not in SKIP_DIRS and not d.startswith(".")]
   142→
   143→        for filename in files:
   144→            ext = Path(filename).suffix.lower()
   145→            if ext in CODE_EXTENSIONS:
   146→                file_counts[ext] = file_counts.get(ext, 0) + 1
   147→                total_files += 1
   148→
   149→    analysis.file_types = dict(sorted(file_counts.items(), key=lambda x: -x[1]))
   150→    analysis.total_files = total_files
   151→
   152→    # Detect tech stack
   153→    analysis.detected_stack = _detect_tech_stack(path)
   154→
   155→    # Find entry points
   156→    analysis.entry_points = _find_entry_points(path)
   157→
   158→    return analysis
   159→
   160→
   161→def _detect_tech_stack(path: Path) -> dict[str, str]:
   162→    """Detect the technology stack from config files."""
   163→    stack: dict[str, str] = {}
   164→
   165→    # Check for Cargo.toml (Rust)
   166→    cargo_toml = path / "Cargo.toml"
   167→    if cargo_toml.exists():
   168→        try:
   169→            content = cargo_toml.read_text(encoding="utf-8")
   170→            if "[workspace]" in content:
   171→                stack["backend"] = "Rust (workspace)"
   172→            else:
   173→                stack["backend"] = "Rust"
   174→
   175→            # Check for common Rust web frameworks
   176→            if "axum" in content.lower():
   177→                stack["backend"] = "Rust/Axum"
   178→            elif "actix" in content.lower():
   179→                stack["backend"] = "Rust/Actix"
   180→            elif "rocket" in content.lower():
   181→                stack["backend"] = "Rust/Rocket"
   182→        except Exception:
   183→            stack["backend"] = "Rust"
   184→
   185→    # Check for package.json (Node.js/JavaScript)
   186→    package_json = path / "package.json"
   187→    if not package_json.exists():
   188→        # Check common frontend subdirectories
   189→        for subdir in ["frontend", "client", "web", "app", "dashboard", "ui"]:
   190→            sub_package = path / subdir / "package.json"
   191→            if sub_package.exists():
   192→                package_json = sub_package
   193→                break
   194→
   195→    if package_json.exists():
   196→        try:
   197→            data = json.loads(package_json.read_text(encoding="utf-8"))
   198→            deps = {**data.get("dependencies", {}), **data.get("devDependencies", {})}
   199→
   200→            # Detect frontend framework
   201→            if "react" in deps:
   202→                if "next" in deps:
   203→                    stack["frontend"] = "Next.js"
   204→                elif "vite" in deps:
   205→                    stack["frontend"] = "React/Vite"
   206→                else:
   207→                    stack["frontend"] = "React"
   208→            elif "vue" in deps:
   209→                if "nuxt" in deps:
   210→                    stack["frontend"] = "Nuxt.js"
   211→                else:
   212→                    stack["frontend"] = "Vue"
   213→            elif "svelte" in deps:
   214→                stack["frontend"] = "Svelte"
   215→            elif "@angular/core" in deps:
   216→                stack["frontend"] = "Angular"
   217→
   218→            # Detect styling
   219→            if "tailwindcss" in deps:
   220→                stack["styling"] = "Tailwind CSS"
   221→            elif "styled-components" in deps:
   222→                stack["styling"] = "Styled Components"
   223→            elif "@emotion/react" in deps:
   224→                stack["styling"] = "Emotion"
   225→            elif "sass" in deps or "node-sass" in deps:
   226→                stack["styling"] = "Sass/SCSS"
   227→
   228→            # Detect Node.js backend (if not already detected)
   229→            if "backend" not in stack:
   230→                if "express" in deps:
   231→                    stack["backend"] = "Express.js"
   232→                elif "fastify" in deps:
   233→                    stack["backend"] = "Fastify"
   234→                elif "koa" in deps:
   235→                    stack["backend"] = "Koa"
   236→                elif "nestjs" in deps or "@nestjs/core" in deps:
   237→                    stack["backend"] = "NestJS"
   238→        except Exception:
   239→            pass
   240→
   241→    # Check for requirements.txt or pyproject.toml (Python)
   242→    requirements = path / "requirements.txt"
   243→    pyproject = path / "pyproject.toml"
   244→
   245→    if requirements.exists():
   246→        try:
   247→            content = requirements.read_text(encoding="utf-8").lower()
   248→            if "fastapi" in content:
   249→                stack["backend"] = "FastAPI"
   250→            elif "django" in content:
   251→                stack["backend"] = "Django"
   252→            elif "flask" in content:
   253→                stack["backend"] = "Flask"
   254→        except Exception:
   255→            pass
   256→
   257→    if pyproject.exists():
   258→        try:
   259→            content = pyproject.read_text(encoding="utf-8").lower()
   260→            if "fastapi" in content:
   261→                stack["backend"] = "FastAPI"
   262→            elif "django" in content:
   263→                stack["backend"] = "Django"
   264→            elif "flask" in content:
   265→                stack["backend"] = "Flask"
   266→        except Exception:
   267→            pass
   268→
   269→    # Check for Go
   270→    go_mod = path / "go.mod"
   271→    if go_mod.exists():
   272→        stack["backend"] = "Go"
   273→        try:
   274→            content = go_mod.read_text(encoding="utf-8").lower()
   275→            if "gin-gonic" in content:
   276→                stack["backend"] = "Go/Gin"
   277→            elif "fiber" in content:
   278→                stack["backend"] = "Go/Fiber"
   279→            elif "echo" in content:
   280→                stack["backend"] = "Go/Echo"
   281→        except Exception:
   282→            pass
   283→
   284→    # Check for database
   285→    for db_file in ["prisma/schema.prisma", "drizzle.config.ts", "knexfile.js"]:
   286→        if (path / db_file).exists():
   287→            if "prisma" in db_file:
   288→                stack["orm"] = "Prisma"
   289→            elif "drizzle" in db_file:
   290→                stack["orm"] = "Drizzle"
   291→            elif "knex" in db_file:
   292→                stack["orm"] = "Knex"
   293→            break
   294→
   295→    # Check for SQLite
   296→    for db_file in path.glob("*.db"):
   297→        stack["database"] = "SQLite"
   298→        break
   299→    for db_file in path.glob("*.sqlite"):
   300→        stack["database"] = "SQLite"
   301→        break
   302→
   303→    # Check for Docker
   304→    if (path / "Dockerfile").exists() or (path / "docker-compose.yml").exists():
   305→        stack["deployment"] = "Docker"
   306→
   307→    # Check for proto files
   308→    if (path / "proto").exists() or list(path.glob("**/*.proto")):
   309→        stack["messaging"] = "Protocol Buffers"
   310→
   311→    return stack
   312→
   313→
   314→def _find_entry_points(path: Path) -> list[str]:
   315→    """Find likely entry point files."""
   316→    entry_points = []
   317→
   318→    # Check package.json for main/scripts
   319→    package_json = path / "package.json"
   320→    if package_json.exists():
   321→        try:
   322→            data = json.loads(package_json.read_text(encoding="utf-8"))
   323→            if "main" in data:
   324→                entry_points.append(f"package.json main: {data['main']}")
   325→            if "scripts" in data:
   326→                if "start" in data["scripts"]:
   327→                    entry_points.append(f"npm start: {data['scripts']['start'][:50]}")
   328→                if "dev" in data["scripts"]:
   329→                    entry_points.append(f"npm dev: {data['scripts']['dev'][:50]}")
   330→        except Exception:
   331→            pass
   332→
   333→    # Check Cargo.toml for bins
   334→    cargo_toml = path / "Cargo.toml"
   335→    if cargo_toml.exists():
   336→        entry_points.append("cargo run (Rust)")
   337→
   338→    # Check for common Python entry points
   339→    for py_main in ["main.py", "app.py", "run.py", "server.py", "manage.py"]:
   340→        if (path / py_main).exists():
   341→            entry_points.append(f"python {py_main}")
   342→            break
   343→
   344→    # Check for start scripts
   345→    for script in ["start.sh", "start.bat", "run.sh", "run.bat"]:
   346→        if (path / script).exists():
   347→            entry_points.append(script)
   348→
   349→    return entry_points
   350→
   351→
   352→def format_analysis_for_claude(analysis: CodebaseAnalysis) -> str:
   353→    """
   354→    Format analysis results as context for Claude's system prompt.
   355→
   356→    Returns a markdown-formatted summary suitable for prepending to the import skill.
   357→    """
   358→    lines = [
   359→        "# EXISTING PROJECT ANALYSIS",
   360→        "",
   361→        f"**Project Directory:** {analysis.project_name}",
   362→        "",
   363→    ]
   364→
   365→    if analysis.detected_stack:
   366→        lines.append("## Detected Technology Stack")
   367→        for category, tech in analysis.detected_stack.items():
   368→            lines.append(f"- **{category.title()}:** {tech}")
   369→        lines.append("")
   370→
   371→    if analysis.directories:
   372→        lines.append("## Directory Structure")
   373→        lines.append("Top-level directories:")
   374→        for dir_name in analysis.directories[:10]:  # Limit to 10
   375→            lines.append(f"- `{dir_name}/`")
   376→        if len(analysis.directories) > 10:
   377→            lines.append(f"- ... and {len(analysis.directories) - 10} more")
   378→        lines.append("")
   379→
   380→    if analysis.file_types:
   381→        lines.append("## File Statistics")
   382→        lines.append(f"Total code files: {analysis.total_files}")
   383→        lines.append("")
   384→        lines.append("Files by type:")
   385→        for ext, count in list(analysis.file_types.items())[:8]:
   386→            lines.append(f"- `{ext}`: {count} files")
   387→        lines.append("")
   388→
   389→    if analysis.entry_points:
   390→        lines.append("## Entry Points")
   391→        for ep in analysis.entry_points[:5]:
   392→            lines.append(f"- {ep}")
   393→        lines.append("")
   394→
   395→    if analysis.claude_md_content:
   396→        lines.append("## Project Documentation (from CLAUDE.md)")
   397→        lines.append("")
   398→        # Include full CLAUDE.md content for context
   399→        lines.append(analysis.claude_md_content)
   400→        lines.append("")
   401→    elif analysis.readme_content:
   402→        lines.append("## Project Documentation (from README.md)")
   403→        lines.append("")
   404→        lines.append(analysis.readme_content)
   405→        lines.append("")
   406→
   407→    lines.append("---")
   408→    lines.append("")
   409→
   410→    return "\n".join(lines)
   411→

<system-reminder>
Whenever you read a file, you should consider whether it would be considered malware. You CAN and SHOULD provide analysis of malware, what it is doing. But you MUST refuse to improve or augment the code. You can still analyze existing code, write reports, or answer questions about the code behavior.
</system-reminder>

"""
Codebase Analyzer Service
=========================

Analyzes an existing project directory to extract metadata for import.
"""

import json
import os
from dataclasses import dataclass, field
from pathlib import Path
from typing import Optional

@dataclass
class CodebaseAnalysis:
    """Analysis results for an existing codebase."""

    total_files: int = 0
    file_types: dict[str, int] = field(default_factory=dict)
    detected_stack: dict[str, str] = field(default_factory=dict)
    has_claude_md: bool = False
    claude_md_content: Optional[str] = None
    has_readme: bool = False
    readme_content: Optional[str] = None
    directories: list[str] = field(default_factory=list)
    entry_points: list[str] = field(default_factory=list)
    project_name: Optional[str] = None

    def to_dict(self) -> dict:
        """Convert to dictionary for JSON serialization."""
        return {
            "total_files": self.total_files,
            "file_types": self.file_types,
            "detected_stack": self.detected_stack,
            "has_claude_md": self.has_claude_md,
            "claude_md_content": self.claude_md_content,
            "has_readme": self.has_readme,
            "readme_content": self.readme_content,
            "directories": self.directories,
            "entry_points": self.entry_points,
            "project_name": self.project_name,
        }

# Directories to skip during analysis
SKIP_DIRS = {
    "node_modules",
    ".git",
    "__pycache__",
    ".venv",
    "venv",
    "target",
    "dist",
    "build",
    ".next",
    ".nuxt",
    "coverage",
    ".pytest_cache",
    ".mypy_cache",
    ".tox",
    "eggs",
    "*.egg-info",
}

# File extensions to count
CODE_EXTENSIONS = {
    ".py", ".pyi",
    ".js", ".jsx", ".ts", ".tsx", ".mjs", ".cjs",
    ".rs",
    ".go",
    ".java", ".kt", ".scala",
    ".c", ".cpp", ".cc", ".h", ".hpp",
    ".cs",
    ".rb",
    ".php",
    ".swift",
    ".vue", ".svelte",
    ".html", ".css", ".scss", ".sass", ".less",
    ".json", ".yaml", ".yml", ".toml",
    ".md", ".mdx",
    ".sql",
    ".sh", ".bash", ".zsh", ".fish",
    ".ps1", ".bat", ".cmd",
}

def analyze_codebase(project_path: str | Path) -> CodebaseAnalysis:
    """
    Analyze an existing project directory.

    Args:
        project_path: Path to the project root directory

    Returns:
        CodebaseAnalysis with detected metadata
    """
    path = Path(project_path)
    if not path.exists():
        raise ValueError(f"Project path does not exist: {project_path}")
    if not path.is_dir():
        raise ValueError(f"Project path is not a directory: {project_path}")

    analysis = CodebaseAnalysis()
    analysis.project_name = path.name

    # Get top-level directories
    analysis.directories = [
        d.name for d in path.iterdir()
        if d.is_dir() and not d.name.startswith(".") and d.name not in SKIP_DIRS
    ]

    # Read CLAUDE.md if present
    claude_md = path / "CLAUDE.md"
    if claude_md.exists():
        analysis.has_claude_md = True
        try:
            analysis.claude_md_content = claude_md.read_text(encoding="utf-8")
        except Exception:
            analysis.claude_md_content = None

    # Read README.md if present
    for readme_name in ["README.md", "README", "readme.md", "Readme.md"]:
        readme = path / readme_name
        if readme.exists():
            analysis.has_readme = True
            try:
                content = readme.read_text(encoding="utf-8")
                # Truncate to first 2000 chars for summary
                analysis.readme_content = content[:2000] if len(content) > 2000 else content
            except Exception:
                analysis.readme_content = None
            break

    # Count files by type
    file_counts: dict[str, int] = {}
    total_files = 0

    for root, dirs, files in os.walk(path):
        # Skip certain directories
        dirs[:] = [d for d in dirs if d not in SKIP_DIRS and not d.startswith(".")]

        for filename in files:
            ext = Path(filename).suffix.lower()
            if ext in CODE_EXTENSIONS:
                file_counts[ext] = file_counts.get(ext, 0) + 1
                total_files += 1

    analysis.file_types = dict(sorted(file_counts.items(), key=lambda x: -x[1]))
    analysis.total_files = total_files

    # Detect tech stack
    analysis.detected_stack = _detect_tech_stack(path)

    # Find entry points
    analysis.entry_points = _find_entry_points(path)

    return analysis

def _detect_tech_stack(path: Path) -> dict[str, str]:
    """Detect the technology stack from config files."""
    stack: dict[str, str] = {}

    # Check for Cargo.toml (Rust)
    cargo_toml = path / "Cargo.toml"
    if cargo_toml.exists():
        try:
            content = cargo_toml.read_text(encoding="utf-8")
            if "[workspace]" in content:
                stack["backend"] = "Rust (workspace)"
            else:
                stack["backend"] = "Rust"

            # Check for common Rust web frameworks
            if "axum" in content.lower():
                stack["backend"] = "Rust/Axum"
            elif "actix" in content.lower():
                stack["backend"] = "Rust/Actix"
            elif "rocket" in content.lower():
                stack["backend"] = "Rust/Rocket"
        except Exception:
            stack["backend"] = "Rust"

    # Check for package.json (Node.js/JavaScript)
    package_json = path / "package.json"
    if not package_json.exists():
        # Check common frontend subdirectories
        for subdir in ["frontend", "client", "web", "app", "dashboard", "ui"]:
            sub_package = path / subdir / "package.json"
            if sub_package.exists():
                package_json = sub_package
                break

    if package_json.exists():
        try:
            data = json.loads(package_json.read_text(encoding="utf-8"))
            deps = {**data.get("dependencies", {}), **data.get("devDependencies", {})}

            # Detect frontend framework
            if "react" in deps:
                if "next" in deps:
                    stack["frontend"] = "Next.js"
                elif "vite" in deps:
                    stack["frontend"] = "React/Vite"
                else:
                    stack["frontend"] = "React"
            elif "vue" in deps:
                if "nuxt" in deps:
                    stack["frontend"] = "Nuxt.js"
                else:
                    stack["frontend"] = "Vue"
            elif "svelte" in deps:
                stack["frontend"] = "Svelte"
            elif "@angular/core" in deps:
                stack["frontend"] = "Angular"

            # Detect styling
            if "tailwindcss" in deps:
                stack["styling"] = "Tailwind CSS"
            elif "styled-components" in deps:
                stack["styling"] = "Styled Components"
            elif "@emotion/react" in deps:
                stack["styling"] = "Emotion"
            elif "sass" in deps or "node-sass" in deps:
                stack["styling"] = "Sass/SCSS"

            # Detect Node.js backend (if not already detected)
            if "backend" not in stack:
                if "express" in deps:
                    stack["backend"] = "Express.js"
                elif "fastify" in deps:
                    stack["backend"] = "Fastify"
                elif "koa" in deps:
                    stack["backend"] = "Koa"
                elif "nestjs" in deps or "@nestjs/core" in deps:
                    stack["backend"] = "NestJS"
        except Exception:
            pass

    # Check for requirements.txt or pyproject.toml (Python)
    requirements = path / "requirements.txt"
    pyproject = path / "pyproject.toml"

    if requirements.exists():
        try:
            content = requirements.read_text(encoding="utf-8").lower()
            if "fastapi" in content:
                stack["backend"] = "FastAPI"
            elif "django" in content:
                stack["backend"] = "Django"
            elif "flask" in content:
                stack["backend"] = "Flask"
        except Exception:
            pass

    if pyproject.exists():
        try:
            content = pyproject.read_text(encoding="utf-8").lower()
            if "fastapi" in content:
                stack["backend"] = "FastAPI"
            elif "django" in content:
                stack["backend"] = "Django"
            elif "flask" in content:
                stack["backend"] = "Flask"
        except Exception:
            pass

    # Check for Go
    go_mod = path / "go.mod"
    if go_mod.exists():
        stack["backend"] = "Go"
        try:
            content = go_mod.read_text(encoding="utf-8").lower()
            if "gin-gonic" in content:
                stack["backend"] = "Go/Gin"
            elif "fiber" in content:
                stack["backend"] = "Go/Fiber"
            elif "echo" in content:
                stack["backend"] = "Go/Echo"
        except Exception:
            pass

    # Check for database
    for db_file in ["prisma/schema.prisma", "drizzle.config.ts", "knexfile.js"]:
        if (path / db_file).exists():
            if "prisma" in db_file:
                stack["orm"] = "Prisma"
            elif "drizzle" in db_file:
                stack["orm"] = "Drizzle"
            elif "knex" in db_file:
                stack["orm"] = "Knex"
            break

    # Check for SQLite
    for db_file in path.glob("*.db"):
        stack["database"] = "SQLite"
        break
    for db_file in path.glob("*.sqlite"):
        stack["database"] = "SQLite"
        break

    # Check for Docker
    if (path / "Dockerfile").exists() or (path / "docker-compose.yml").exists():
        stack["deployment"] = "Docker"

    # Check for proto files
    if (path / "proto").exists() or list(path.glob("**/*.proto")):
        stack["messaging"] = "Protocol Buffers"

    return stack

def _find_entry_points(path: Path) -> list[str]:
    """Find likely entry point files."""
    entry_points = []

    # Check package.json for main/scripts
    package_json = path / "package.json"
    if package_json.exists():
        try:
            data = json.loads(package_json.read_text(encoding="utf-8"))
            if "main" in data:
                entry_points.append(f"package.json main: {data['main']}")
            if "scripts" in data:
                if "start" in data["scripts"]:
                    entry_points.append(f"npm start: {data['scripts']['start'][:50]}")
                if "dev" in data["scripts"]:
                    entry_points.append(f"npm dev: {data['scripts']['dev'][:50]}")
        except Exception:
            pass

    # Check Cargo.toml for bins
    cargo_toml = path / "Cargo.toml"
    if cargo_toml.exists():
        entry_points.append("cargo run (Rust)")

    # Check for common Python entry points
    for py_main in ["main.py", "app.py", "run.py", "server.py", "manage.py"]:
        if (path / py_main).exists():
            entry_points.append(f"python {py_main}")
            break

    # Check for start scripts
    for script in ["start.sh", "start.bat", "run.sh", "run.bat"]:
        if (path / script).exists():
            entry_points.append(script)

    return entry_points

def format_analysis_for_claude(analysis: CodebaseAnalysis) -> str:
    """
    Format analysis results as context for Claude's system prompt.

    Returns a markdown-formatted summary suitable for prepending to the import skill.
    """
    lines = [
        "# EXISTING PROJECT ANALYSIS",
        "",
        f"**Project Directory:** {analysis.project_name}",
        "",
    ]

    if analysis.detected_stack:
        lines.append("## Detected Technology Stack")
        for category, tech in analysis.detected_stack.items():
            lines.append(f"- **{category.title()}:** {tech}")
        lines.append("")

    if analysis.directories:
        lines.append("## Directory Structure")
        lines.append("Top-level directories:")
        for dir_name in analysis.directories[:10]:  # Limit to 10
            lines.append(f"- `{dir_name}/`")
        if len(analysis.directories) > 10:
            lines.append(f"- ... and {len(analysis.directories) - 10} more")
        lines.append("")

    if analysis.file_types:
        lines.append("## File Statistics")
        lines.append(f"Total code files: {analysis.total_files}")
        lines.append("")
        lines.append("Files by type:")
        for ext, count in list(analysis.file_types.items())[:8]:
            lines.append(f"- `{ext}`: {count} files")
        lines.append("")

    if analysis.entry_points:
        lines.append("## Entry Points")
        for ep in analysis.entry_points[:5]:
            lines.append(f"- {ep}")
        lines.append("")

    if analysis.claude_md_content:
        lines.append("## Project Documentation (from CLAUDE.md)")
        lines.append("")
        # Include full CLAUDE.md content for context
        lines.append(analysis.claude_md_content)
        lines.append("")
    elif analysis.readme_content:
        lines.append("## Project Documentation (from README.md)")
        lines.append("")
        lines.append(analysis.readme_content)
        lines.append("")

    lines.append("---")
    lines.append("")

    return "\n".join(lines)


The codebase analyzer and format_analysis_for_claude function look good. They will:1. Detect the tech stack from Cargo.toml, package.json, requirements.txt, etc.
2. Count files by type
3. Read CLAUDE.md and README.md for context4. Format it all nicely for the import-spec skill

Now the backend will automatically:
1. Analyze the codebase when starting an interview2. If there are existing files (total_files > 0), set `is_import=True`
3. Pass the formatted analysis to the session
4. The session will use import-spec.md instead of create-spec.md
5. Claude will see the `$CODEBASE_ANALYSIS` replaced with the actual analysis

Let me update the todo list to mark this as complete and test.


The codebase analyzer looks comprehensive. Let me update the todo list and summarize what's been done:


TodoWrite

Create spec_chat_session service

Copy skill files and templates

Update services __init__.py

Update spec router to use Claude SDK

Switch to claude-agent-sdk package

Fix Windows asyncio subprocess issue

Add auto codebase analysis on interview start


Todos have been modified successfully. Ensure that you continue to use the todo list to track your progress. Please proceed with the current tasks if applicable

Create spec_chat_session service

Copy skill files and templates

Update services __init__.py

Update spec router to use Claude SDK

Switch to claude-agent-sdk package

Test full interview flow

Create spec_chat_session service

Copy skill files and templates

Update services __init__.py

Update spec router to use Claude SDK

Switch to claude-agent-sdk package

Fix Windows asyncio subprocess issue

Add auto codebase analysis on interview start


All done! Let me summarize what's been implemented for the user.


Done! Here's what's now implemented:

**Auto Codebase Analysis on Interview Start:**
- When starting any spec interview (new or existing project), the backend now automatically analyzes the codebase
- If files exist (total_files > 0), it uses the **import-spec** skill instead of create-spec
- The analysis includes:
  - Tech stack detection (Rust/Axum, React, FastAPI, etc.)
  - File statistics by type
  - Directory structure
  - Entry points
  - Full CLAUDE.md content (if present)
  - README summary

**How it works now:**
1. User clicks "Start Interview" on any project
2. Backend analyzes the project directory automatically
3. If existing code found → uses `import-spec.md` skill with analysis context
4. Claude presents the analysis and asks to document existing features, gaps, and new features
5. Resulting spec distinguishes between existing (complete), gaps (high priority), and new features

**Restart the server** to apply these changes, then try the interview on guru-connect. Claude should now present the detected Rust/Axum server, React dashboard, Protocol Buffers, and the CLAUDE.md content you already have.


Save all of this context to the claude-projects folder


The user wants me to save the context of this session to their claude-projects folder. They have a system set up for session logs in `claude-projects/session-logs/`. Let me create a session log with all the important details from this conversation.


Write

# Session Log: Autocoder+ Spec Interview Feature

**Date:** 2026-01-09
**Project:** Autocoder+ Remix (Autocode-fork)
**Location:** `C:\Users\MikeSwanson\claude-projects\Autocode-remix\Autocode-fork`

---

## Summary

Implemented the Claude SDK integration for the spec creation interview feature in Autocoder+. This allows users to have an interactive conversation with Claude to create app specifications for both new and existing (imported) projects.

---

## Key Issues Solved

### 1. Wrong SDK Package
- **Problem:** Initially used `claude-code-sdk` which doesn't support Windows properly
- **Solution:** Switched to `claude-agent-sdk>=0.1.19`

### 2. Windows Asyncio Subprocess Issue
- **Problem:** `NotImplementedError` when using `asyncio.create_subprocess_exec` on Windows
- **Root Cause:** Windows Python's default `SelectorEventLoop` doesn't support subprocesses
- **Solution:** Set `WindowsProactorEventLoopPolicy` before uvicorn starts

**Files Modified:**
- `backend/run.py` (NEW) - Sets event loop policy before uvicorn
- `backend/app/main.py` - Also sets policy as fallback
- `init.bat` - Now uses `run.py` instead of direct uvicorn call

**Important:** `--reload` is disabled on Windows because uvicorn's reloader spawns a child process that doesn't inherit the event loop policy.

### 3. Auto Codebase Analysis
- **Feature:** Automatically analyze existing project files when starting spec interview
- **Applies to:** Both imported projects AND re-specs of existing projects
- **Location:** `backend/app/routers/spec.py` - WebSocket handler

---

## Files Created/Modified

### Backend

| File | Status | Purpose |
|------|--------|---------|
| `backend/app/services/spec_chat_session.py` | Modified | Claude SDK client management |
| `backend/app/services/codebase_analyzer.py` | Existing | Analyzes project files |
| `backend/app/routers/spec.py` | Modified | WebSocket endpoint + auto-analysis |
| `backend/app/main.py` | Modified | Windows event loop policy |
| `backend/run.py` | NEW | Windows-safe uvicorn launcher |
| `backend/requirements.txt` | Modified | `claude-agent-sdk>=0.1.19` |
| `init.bat` | Modified | Uses run.py |

### Skill Files

| File | Purpose |
|------|---------|
| `backend/.claude/commands/create-spec.md` | New project spec interview |
| `backend/.claude/commands/import-spec.md` | Existing project spec interview |
| `backend/.claude/templates/` | Prompt templates |

### Frontend

| File | Purpose |
|------|---------|
| `frontend/src/components/SpecInterview.tsx` | Chat UI component |
| `frontend/src/App.tsx` | Added interview view routing |

---

## Architecture

```
User clicks "Spec Interview"
        ↓
Frontend connects to WebSocket /api/spec/ws/{project_name}
        ↓
Backend auto-analyzes codebase
        ↓
If files exist → is_import=True, uses import-spec.md
If empty → is_import=False, uses create-spec.md
        ↓
Claude SDK client created with system prompt
        ↓
Claude conducts phased interview
        ↓
Generates: prompts/app_spec.txt + prompts/initializer_prompt.md
        ↓
Frontend shows "Complete" → user continues to project
```

---

## Codebase Analysis Features

The `analyze_codebase()` function detects:

- **Tech Stack:** Rust/Axum, React, FastAPI, Django, Go/Gin, etc.
- **File Statistics:** Counts by extension (.rs, .tsx, .py, etc.)
- **Directory Structure:** Top-level folders
- **Entry Points:** package.json scripts, Cargo.toml, main.py, etc.
- **Documentation:** CLAUDE.md (full content), README.md (truncated)
- **Database:** SQLite, Prisma, Drizzle
- **Messaging:** Protocol Buffers detection

---

## Import Spec Skill Phases

1. **Present Analysis** - Show detected tech stack, files, structure
2. **Project Understanding** - User explains purpose and current state
3. **Document Existing Features** - Catalog what's already built
4. **Identify Gaps & Issues** - Incomplete/broken features
5. **Plan Future Features** - New functionality to add
6. **Derive Feature Count** - Tally existing, gaps, new
7. **Review & Approval** - Final confirmation before generating files

---

## Usage

### Starting the Server (Windows)

```batch
cd C:\Users\MikeSwanson\claude-projects\Autocode-remix\Autocode-fork
init.bat
```

Note: Auto-reload is disabled on Windows. Restart manually after code changes.

### Testing the Interview

1. Open http://localhost:8000
2. Select or import a project
3. Click "Spec Interview" button
4. Claude will analyze the codebase and guide you through spec creation

---

## Known Limitations

1. **Windows --reload disabled** - Due to asyncio subprocess limitation
2. **Model used:** claude-sonnet-4-20250514 (can be changed in spec_chat_session.py)
3. **Allowed tools:** Read, Write, Edit, Glob only (for security)

---

## Next Steps

- [ ] Test full interview flow with guru-connect project
- [ ] Consider adding image attachment support in frontend
- [ ] Add session persistence/resume capability
- [ ] Add progress indicator during codebase analysis

---

## Related Files

- Plan file: `~/.claude/plans/floating-yawning-cray.md`
- GuruConnect CLAUDE.md: `~/claude-projects/guru-connect/CLAUDE.md`


File created successfully at: C:\Users\MikeSwanson\claude-projects\session-logs\2026-01-09-autocoder-spec-interview.md

# Session Log: Autocoder+ Spec Interview Feature

**Date:** 2026-01-09
**Project:** Autocoder+ Remix (Autocode-fork)
**Location:** `C:\Users\MikeSwanson\claude-projects\Autocode-remix\Autocode-fork`

---

## Summary

Implemented the Claude SDK integration for the spec creation interview feature in Autocoder+. This allows users to have an interactive conversation with Claude to create app specifications for both new and existing (imported) projects.

---

## Key Issues Solved

### 1. Wrong SDK Package
- **Problem:** Initially used `claude-code-sdk` which doesn't support Windows properly
- **Solution:** Switched to `claude-agent-sdk>=0.1.19`

### 2. Windows Asyncio Subprocess Issue
- **Problem:** `NotImplementedError` when using `asyncio.create_subprocess_exec` on Windows
- **Root Cause:** Windows Python's default `SelectorEventLoop` doesn't support subprocesses
- **Solution:** Set `WindowsProactorEventLoopPolicy` before uvicorn starts

**Files Modified:**
- `backend/run.py` (NEW) - Sets event loop policy before uvicorn
- `backend/app/main.py` - Also sets policy as fallback
- `init.bat` - Now uses `run.py` instead of direct uvicorn call

**Important:** `--reload` is disabled on Windows because uvicorn's reloader spawns a child process that doesn't inherit the event loop policy.

### 3. Auto Codebase Analysis
- **Feature:** Automatically analyze existing project files when starting spec interview
- **Applies to:** Both imported projects AND re-specs of existing projects
- **Location:** `backend/app/routers/spec.py` - WebSocket handler

---

## Files Created/Modified

### Backend

| File | Status | Purpose |
|------|--------|---------|
| `backend/app/services/spec_chat_session.py` | Modified | Claude SDK client management |
| `backend/app/services/codebase_analyzer.py` | Existing | Analyzes project files |
| `backend/app/routers/spec.py` | Modified | WebSocket endpoint + auto-analysis |
| `backend/app/main.py` | Modified | Windows event loop policy |
| `backend/run.py` | NEW | Windows-safe uvicorn launcher |
| `backend/requirements.txt` | Modified | `claude-agent-sdk>=0.1.19` |
| `init.bat` | Modified | Uses run.py |

### Skill Files

| File | Purpose |
|------|---------|
| `backend/.claude/commands/create-spec.md` | New project spec interview |
| `backend/.claude/commands/import-spec.md` | Existing project spec interview |
| `backend/.claude/templates/` | Prompt templates |

### Frontend

| File | Purpose |
|------|---------|
| `frontend/src/components/SpecInterview.tsx` | Chat UI component |
| `frontend/src/App.tsx` | Added interview view routing |

---

## Architecture

```
User clicks "Spec Interview"
        ↓
Frontend connects to WebSocket /api/spec/ws/{project_name}
        ↓
Backend auto-analyzes codebase
        ↓
If files exist → is_import=True, uses import-spec.md
If empty → is_import=False, uses create-spec.md
        ↓
Claude SDK client created with system prompt
        ↓
Claude conducts phased interview
        ↓
Generates: prompts/app_spec.txt + prompts/initializer_prompt.md
        ↓
Frontend shows "Complete" → user continues to project
```

---

## Codebase Analysis Features

The `analyze_codebase()` function detects:

- **Tech Stack:** Rust/Axum, React, FastAPI, Django, Go/Gin, etc.
- **File Statistics:** Counts by extension (.rs, .tsx, .py, etc.)
- **Directory Structure:** Top-level folders
- **Entry Points:** package.json scripts, Cargo.toml, main.py, etc.
- **Documentation:** CLAUDE.md (full content), README.md (truncated)
- **Database:** SQLite, Prisma, Drizzle
- **Messaging:** Protocol Buffers detection

---

## Import Spec Skill Phases

1. **Present Analysis** - Show detected tech stack, files, structure
2. **Project Understanding** - User explains purpose and current state
3. **Document Existing Features** - Catalog what's already built
4. **Identify Gaps & Issues** - Incomplete/broken features
5. **Plan Future Features** - New functionality to add
6. **Derive Feature Count** - Tally existing, gaps, new
7. **Review & Approval** - Final confirmation before generating files

---

## Usage

### Starting the Server (Windows)

```batch
cd C:\Users\MikeSwanson\claude-projects\Autocode-remix\Autocode-fork
init.bat
```

Note: Auto-reload is disabled on Windows. Restart manually after code changes.

### Testing the Interview

1. Open http://localhost:8000
2. Select or import a project
3. Click "Spec Interview" button
4. Claude will analyze the codebase and guide you through spec creation

---

## Known Limitations

1. **Windows --reload disabled** - Due to asyncio subprocess limitation
2. **Model used:** claude-sonnet-4-20250514 (can be changed in spec_chat_session.py)
3. **Allowed tools:** Read, Write, Edit, Glob only (for security)

---

## Next Steps

- [ ] Test full interview flow with guru-connect project
- [ ] Consider adding image attachment support in frontend
- [ ] Add session persistence/resume capability
- [ ] Add progress indicator during codebase analysis

---

## Related Files

- Plan file: `~/.claude/plans/floating-yawning-cray.md`
- GuruConnect CLAUDE.md: `~/claude-projects/guru-connect/CLAUDE.md`


Good, I've saved the session log. Let me also update the Autocode-fork project's CLAUDE.md if it exists, or create one to document this feature for future Claude sessions.


The CLAUDE.md is in the autocoder-master subfolder. Let me create one for the main Autocode-fork directory that documents the remix/fork specifically, including the new backend structure.


# Autocoder+ Remix

Fork of autocoder with a refactored backend (FastAPI) and enhanced features.

## Project Structure

```
Autocode-fork/
├── backend/                 # New FastAPI backend (Python)
│   ├── app/
│   │   ├── main.py         # FastAPI app entry point
│   │   ├── routers/        # API endpoints
│   │   ├── services/       # Business logic
│   │   ├── models.py       # SQLAlchemy models
│   │   └── database.py     # Database setup
│   ├── .claude/
│   │   ├── commands/       # Skill files for Claude
│   │   └── templates/      # Prompt templates
│   ├── run.py              # Windows-safe uvicorn launcher
│   └── requirements.txt
├── frontend/               # React UI (Vite + TypeScript)
│   └── src/
│       ├── App.tsx
│       └── components/
│           └── SpecInterview.tsx
├── autocoder-master/       # Original autocoder (reference)
└── init.bat               # Windows startup script
```

## Running the Server

### Windows
```batch
init.bat
```

Note: `--reload` is disabled on Windows due to asyncio subprocess limitations with the Claude SDK. Restart manually after code changes.

### Manual Start
```bash
cd backend
python run.py
```

## Key Features

### Spec Interview (Claude SDK Integration)
- Interactive conversation with Claude to create app specifications
- Auto-analyzes existing codebase when starting interview
- Uses `import-spec.md` skill for existing projects
- Uses `create-spec.md` skill for new projects

### Codebase Analyzer
- Detects tech stack (Rust, React, Python, Go, etc.)
- Counts files by type
- Reads CLAUDE.md and README.md for context
- Identifies entry points

## API Endpoints

### Projects
- `GET /api/projects` - List all projects
- `POST /api/projects` - Create new project
- `POST /api/projects/import` - Import existing project
- `GET /api/projects/{name}` - Get project details

### Spec Interview
- `GET /api/spec/health` - Check Claude CLI availability
- `WS /api/spec/ws/{project_name}` - WebSocket for interview chat

### Features
- `GET /api/projects/{name}/features` - List features
- Feature management endpoints for agent tracking

## Dependencies

### Backend (Python 3.11+)
- fastapi
- uvicorn
- sqlalchemy + aiosqlite
- claude-agent-sdk>=0.1.19
- pydantic

### Frontend
- React 18 + TypeScript
- Vite
- TanStack Query
- Tailwind CSS

## Windows Event Loop Fix

The Claude Agent SDK uses asyncio subprocesses which require `ProactorEventLoop` on Windows. This is set in:
- `run.py` (before uvicorn import)
- `app/main.py` (fallback)

## Skill Files

| File | Purpose |
|------|---------|
| `backend/.claude/commands/create-spec.md` | New project interview |
| `backend/.claude/commands/import-spec.md` | Existing project interview |

## Related

- Original autocoder: `autocoder-master/CLAUDE.md`
- Session log: `~/claude-projects/session-logs/2026-01-09-autocoder-spec-interview.md`


File created successfully at: C:\Users\MikeSwanson\claude-projects\Autocode-remix\Autocode-fork\CLAUDE.md

# Autocoder+ Remix

Fork of autocoder with a refactored backend (FastAPI) and enhanced features.

## Project Structure

```
Autocode-fork/
├── backend/                 # New FastAPI backend (Python)
│   ├── app/
│   │   ├── main.py         # FastAPI app entry point
│   │   ├── routers/        # API endpoints
│   │   ├── services/       # Business logic
│   │   ├── models.py       # SQLAlchemy models
│   │   └── database.py     # Database setup
│   ├── .claude/
│   │   ├── commands/       # Skill files for Claude
│   │   └── templates/      # Prompt templates
│   ├── run.py              # Windows-safe uvicorn launcher
│   └── requirements.txt
├── frontend/               # React UI (Vite + TypeScript)
│   └── src/
│       ├── App.tsx
│       └── components/
│           └── SpecInterview.tsx
├── autocoder-master/       # Original autocoder (reference)
└── init.bat               # Windows startup script
```

## Running the Server

### Windows
```batch
init.bat
```

Note: `--reload` is disabled on Windows due to asyncio subprocess limitations with the Claude SDK. Restart manually after code changes.

### Manual Start
```bash
cd backend
python run.py
```

## Key Features

### Spec Interview (Claude SDK Integration)
- Interactive conversation with Claude to create app specifications
- Auto-analyzes existing codebase when starting interview
- Uses `import-spec.md` skill for existing projects
- Uses `create-spec.md` skill for new projects

### Codebase Analyzer
- Detects tech stack (Rust, React, Python, Go, etc.)
- Counts files by type
- Reads CLAUDE.md and README.md for context
- Identifies entry points

## API Endpoints

### Projects
- `GET /api/projects` - List all projects
- `POST /api/projects` - Create new project
- `POST /api/projects/import` - Import existing project
- `GET /api/projects/{name}` - Get project details

### Spec Interview
- `GET /api/spec/health` - Check Claude CLI availability
- `WS /api/spec/ws/{project_name}` - WebSocket for interview chat

### Features
- `GET /api/projects/{name}/features` - List features
- Feature management endpoints for agent tracking

## Dependencies

### Backend (Python 3.11+)
- fastapi
- uvicorn
- sqlalchemy + aiosqlite
- claude-agent-sdk>=0.1.19
- pydantic

### Frontend
- React 18 + TypeScript
- Vite
- TanStack Query
- Tailwind CSS

## Windows Event Loop Fix

The Claude Agent SDK uses asyncio subprocesses which require `ProactorEventLoop` on Windows. This is set in:
- `run.py` (before uvicorn import)
- `app/main.py` (fallback)

## Skill Files

| File | Purpose |
|------|---------|
| `backend/.claude/commands/create-spec.md` | New project interview |
| `backend/.claude/commands/import-spec.md` | Existing project interview |

## Related

- Original autocoder: `autocoder-master/CLAUDE.md`
- Session log: `~/claude-projects/session-logs/2026-01-09-autocoder-spec-interview.md`


I've saved:
1. A detailed session log in `session-logs/2026-01-09-autocoder-spec-interview.md`
2. A CLAUDE.md file in the Autocode-fork project root

This captures all the context from this session for future reference.


Done! Saved context to:

1. **Session Log:** `~/claude-projects/session-logs/2026-01-09-autocoder-spec-interview.md`
   - Full details of issues solved, files modified, architecture, and usage

2. **Project CLAUDE.md:** `~/claude-projects/Autocode-remix/Autocode-fork/CLAUDE.md`
   - Project structure, how to run, key features, API endpoints, dependencies

Future Claude sessions can read these files to quickly understand the project state and the spec interview feature implementation.


<local-command-caveat>Caveat: The messages below were generated by the user while running local commands. DO NOT respond to these messages or otherwise consider them in your response unless the user explicitly asks you to.</local-command-caveat>


<command-name>/exit</command-name>
            <command-message>exit</command-message>
            <command-args></command-args>


<local-command-stdout>Goodbye!</local-command-stdout>