diff --git a/.claude/commands/checkpoint.md b/.claude/commands/checkpoint.md
new file mode 100644
index 0000000..4787866
--- /dev/null
+++ b/.claude/commands/checkpoint.md
@@ -0,0 +1,40 @@
+---
+description: Create commit with detailed comment
+---
+
+Please create a comprehensive checkpoint commit with the following steps:
+
+1. **Initialize Git if needed**: Run `git init` if git has not been instantiated for the project yet.
+
+2. **Analyze all changes**:
+
+ - Run `git status` to see all tracked and untracked files
+ - Run `git diff` to see detailed changes in tracked files
+ - Run `git log -5 --oneline` to understand the commit message style of this repository
+
+3. **Stage everything**:
+
+ - Add ALL tracked changes (modified and deleted files)
+ - Add ALL untracked files (new files)
+ - Use `git add -A` or `git add .` to stage everything
+
+4. **Create a detailed commit message**:
+
+ - **First line**: Write a clear, concise summary (50-72 chars) describing the primary change
+ - Use imperative mood (e.g., "Add feature" not "Added feature")
+ - Examples: "feat: add user authentication", "fix: resolve database connection issue", "refactor: improve API route structure"
+ - **Body**: Provide a detailed description including:
+ - What changes were made (list of key modifications)
+ - Why these changes were made (purpose/motivation)
+ - Any important technical details or decisions
+ - Breaking changes or migration notes if applicable
+ - **Footer**: Include co-author attribution as shown in the Git Safety Protocol
+
+5. **Execute the commit**: Create the commit with the properly formatted message following this repository's conventions.
+
+IMPORTANT:
+
+- Do NOT skip any files - include everything
+- Make the commit message descriptive enough that someone reviewing the git log can understand what was accomplished
+- Follow the project's existing commit message conventions (check git log first)
+- Include the Claude Code co-author attribution in the commit message
diff --git a/.claude/commands/create-spec.md b/.claude/commands/create-spec.md
index b26a22a..9c8aa8c 100644
--- a/.claude/commands/create-spec.md
+++ b/.claude/commands/create-spec.md
@@ -459,10 +459,19 @@ Create a new file using this XML structure:
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.
-Update the feature count references to match the derived count from Phase 4L:
+**CRITICAL: You MUST update the feature count placeholder:**
-- Line containing "create ... test cases" - update to the derived feature count
-- Line containing "Minimum ... features" - update to the derived feature count
+1. Find the line containing `**[FEATURE_COUNT]**` in the "REQUIRED FEATURE COUNT" section
+2. Replace `[FEATURE_COUNT]` with the exact number agreed upon in Phase 4L (e.g., `25`)
+3. The result should read like: `You must create exactly **25** features using the...`
+
+**Example edit:**
+```
+Before: **CRITICAL:** You must create exactly **[FEATURE_COUNT]** features using the `feature_create_bulk` tool.
+After: **CRITICAL:** You must create exactly **25** features using the `feature_create_bulk` tool.
+```
+
+**Verify the update:** After editing, read the file again to confirm the feature count appears correctly. If `[FEATURE_COUNT]` still appears in the file, the update failed and you must try again.
**Note:** You do NOT need to update `coding_prompt.md` - the coding agent works through features one at a time regardless of total count.
diff --git a/.claude/templates/coding_prompt_yolo.template.md b/.claude/templates/coding_prompt_yolo.template.md
new file mode 100644
index 0000000..5e2f1b7
--- /dev/null
+++ b/.claude/templates/coding_prompt_yolo.template.md
@@ -0,0 +1,274 @@
+
+
+
+## YOLO MODE - Rapid Prototyping (Testing Disabled)
+
+**WARNING:** This mode skips all browser testing and regression tests.
+Features are marked as passing after lint/type-check succeeds.
+Use for rapid prototyping only - not for production-quality development.
+
+---
+
+## YOUR ROLE - CODING AGENT (YOLO MODE)
+
+You are continuing work on a long-running autonomous development task.
+This is a FRESH context window - you have no memory of previous sessions.
+
+### STEP 1: GET YOUR BEARINGS (MANDATORY)
+
+Start by orienting yourself:
+
+```bash
+# 1. See your working directory
+pwd
+
+# 2. List files to understand project structure
+ls -la
+
+# 3. Read the project specification to understand what you're building
+cat app_spec.txt
+
+# 4. Read progress notes from previous sessions
+cat claude-progress.txt
+
+# 5. Check recent git history
+git log --oneline -20
+```
+
+Then use MCP tools to check feature status:
+
+```
+# 6. Get progress statistics (passing/total counts)
+Use the feature_get_stats tool
+
+# 7. Get the next feature to work on
+Use the feature_get_next tool
+```
+
+Understanding the `app_spec.txt` is critical - it contains the full requirements
+for the application you're building.
+
+### STEP 2: START SERVERS (IF NOT RUNNING)
+
+If `init.sh` exists, run it:
+
+```bash
+chmod +x init.sh
+./init.sh
+```
+
+Otherwise, start servers manually and document the process.
+
+### STEP 3: CHOOSE ONE FEATURE TO IMPLEMENT
+
+Get the next feature to implement:
+
+```
+# Get the highest-priority pending feature
+Use the feature_get_next tool
+```
+
+Once you've retrieved the feature, **immediately mark it as in-progress**:
+
+```
+# Mark feature as in-progress to prevent other sessions from working on it
+Use the feature_mark_in_progress tool with feature_id=42
+```
+
+Focus on completing one feature in this session before moving on to other features.
+It's ok if you only complete one feature in this session, as there will be more sessions later that continue to make progress.
+
+#### When to Skip a Feature (EXTREMELY RARE)
+
+**Skipping should almost NEVER happen.** Only skip for truly external blockers you cannot control:
+
+- **External API not configured**: Third-party service credentials missing (e.g., Stripe keys, OAuth secrets)
+- **External service unavailable**: Dependency on service that's down or inaccessible
+- **Environment limitation**: Hardware or system requirement you cannot fulfill
+
+**NEVER skip because:**
+
+| Situation | Wrong Action | Correct Action |
+|-----------|--------------|----------------|
+| "Page doesn't exist" | Skip | Create the page |
+| "API endpoint missing" | Skip | Implement the endpoint |
+| "Database table not ready" | Skip | Create the migration |
+| "Component not built" | Skip | Build the component |
+| "No data to test with" | Skip | Create test data or build data entry flow |
+| "Feature X needs to be done first" | Skip | Build feature X as part of this feature |
+
+If a feature requires building other functionality first, **build that functionality**. You are the coding agent - your job is to make the feature work, not to defer it.
+
+If you must skip (truly external blocker only):
+
+```
+Use the feature_skip tool with feature_id={id}
+```
+
+Document the SPECIFIC external blocker in `claude-progress.txt`. "Functionality not built" is NEVER a valid reason.
+
+### STEP 4: IMPLEMENT THE FEATURE
+
+Implement the chosen feature thoroughly:
+
+1. Write the code (frontend and/or backend as needed)
+2. Ensure proper error handling
+3. Follow existing code patterns in the codebase
+
+### STEP 5: VERIFY WITH LINT AND TYPE CHECK (YOLO MODE)
+
+**In YOLO mode, verification is done through static analysis only.**
+
+Run the appropriate lint and type-check commands for your project:
+
+**For TypeScript/JavaScript projects:**
+```bash
+npm run lint
+npm run typecheck # or: npx tsc --noEmit
+```
+
+**For Python projects:**
+```bash
+ruff check .
+mypy .
+```
+
+**If lint/type-check passes:** Proceed to mark the feature as passing.
+
+**If lint/type-check fails:** Fix the errors before proceeding.
+
+### STEP 6: UPDATE FEATURE STATUS
+
+**YOU CAN ONLY MODIFY ONE FIELD: "passes"**
+
+After lint/type-check passes, mark the feature as passing:
+
+```
+# Mark feature #42 as passing (replace 42 with the actual feature ID)
+Use the feature_mark_passing tool with feature_id=42
+```
+
+**NEVER:**
+
+- Delete features
+- Edit feature descriptions
+- Modify feature steps
+- Combine or consolidate features
+- Reorder features
+
+### STEP 7: COMMIT YOUR PROGRESS
+
+Make a descriptive git commit:
+
+```bash
+git add .
+git commit -m "Implement [feature name] - YOLO mode
+
+- Added [specific changes]
+- Lint/type-check passing
+- Marked feature #X as passing
+"
+```
+
+### STEP 8: UPDATE PROGRESS NOTES
+
+Update `claude-progress.txt` with:
+
+- What you accomplished this session
+- Which feature(s) you completed
+- Any issues discovered or fixed
+- What should be worked on next
+- Current completion status (e.g., "45/200 features passing")
+
+### STEP 9: END SESSION CLEANLY
+
+Before context fills up:
+
+1. Commit all working code
+2. Update claude-progress.txt
+3. Mark features as passing if lint/type-check verified
+4. Ensure no uncommitted changes
+5. Leave app in working state
+
+---
+
+## FEATURE TOOL USAGE RULES (CRITICAL - DO NOT VIOLATE)
+
+The feature tools exist to reduce token usage. **DO NOT make exploratory queries.**
+
+### ALLOWED Feature Tools (ONLY these):
+
+```
+# 1. Get progress stats (passing/in_progress/total counts)
+feature_get_stats
+
+# 2. Get the NEXT feature to work on (one feature only)
+feature_get_next
+
+# 3. Mark a feature as in-progress (call immediately after feature_get_next)
+feature_mark_in_progress with feature_id={id}
+
+# 4. Mark a feature as passing (after lint/type-check succeeds)
+feature_mark_passing with feature_id={id}
+
+# 5. Skip a feature (moves to end of queue) - ONLY when blocked by dependency
+feature_skip with feature_id={id}
+
+# 6. Clear in-progress status (when abandoning a feature)
+feature_clear_in_progress with feature_id={id}
+```
+
+### RULES:
+
+- Do NOT try to fetch lists of all features
+- Do NOT query features by category
+- Do NOT list all pending features
+
+**You do NOT need to see all features.** The feature_get_next tool tells you exactly what to work on. Trust it.
+
+---
+
+## EMAIL INTEGRATION (DEVELOPMENT MODE)
+
+When building applications that require email functionality (password resets, email verification, notifications, etc.), you typically won't have access to a real email service or the ability to read email inboxes.
+
+**Solution:** Configure the application to log emails to the terminal instead of sending them.
+
+- Password reset links should be printed to the console
+- Email verification links should be printed to the console
+- Any notification content should be logged to the terminal
+
+**During testing:**
+
+1. Trigger the email action (e.g., click "Forgot Password")
+2. Check the terminal/server logs for the generated link
+3. Use that link directly to verify the functionality works
+
+This allows you to fully test email-dependent flows without needing external email services.
+
+---
+
+## IMPORTANT REMINDERS (YOLO MODE)
+
+**Your Goal:** Rapidly prototype the application with all features implemented
+
+**This Session's Goal:** Complete at least one feature
+
+**Quality Bar (YOLO Mode):**
+
+- Code compiles without errors (lint/type-check passing)
+- Follows existing code patterns
+- Basic error handling in place
+- Features are implemented according to spec
+
+**Note:** Browser testing and regression testing are SKIPPED in YOLO mode.
+Features may have bugs that would be caught by manual testing.
+Use standard mode for production-quality verification.
+
+**You have unlimited time.** Take as long as needed to implement features correctly.
+The most important thing is that you leave the code base in a clean state before
+terminating the session (Step 9).
+
+---
+
+Begin by running Step 1 (Get Your Bearings).
diff --git a/.claude/templates/initializer_prompt.template.md b/.claude/templates/initializer_prompt.template.md
index 742a834..312cd17 100644
--- a/.claude/templates/initializer_prompt.template.md
+++ b/.claude/templates/initializer_prompt.template.md
@@ -9,6 +9,16 @@ Start by reading `app_spec.txt` in your working directory. This file contains
the complete specification for what you need to build. Read it carefully
before proceeding.
+---
+
+## REQUIRED FEATURE COUNT
+
+**CRITICAL:** You must create exactly **[FEATURE_COUNT]** features using the `feature_create_bulk` tool.
+
+This number was determined during spec creation and must be followed precisely. Do not create more or fewer features than specified.
+
+---
+
### CRITICAL FIRST TASK: Create Features
Based on `app_spec.txt`, create features using the feature_create_bulk tool. The features are stored in a SQLite database,
diff --git a/CLAUDE.md b/CLAUDE.md
index 13feb97..dc0f5e0 100644
--- a/CLAUDE.md
+++ b/CLAUDE.md
@@ -42,8 +42,35 @@ python start.py
# Run agent directly for a project (use absolute path or registered name)
python autonomous_agent_demo.py --project-dir C:/Projects/my-app
python autonomous_agent_demo.py --project-dir my-app # if registered
+
+# YOLO mode: rapid prototyping without browser testing
+python autonomous_agent_demo.py --project-dir my-app --yolo
```
+### YOLO Mode (Rapid Prototyping)
+
+YOLO mode skips all testing for faster feature iteration:
+
+```bash
+# CLI
+python autonomous_agent_demo.py --project-dir my-app --yolo
+
+# UI: Toggle the lightning bolt button before starting the agent
+```
+
+**What's different in YOLO mode:**
+- No regression testing (skips `feature_get_for_regression`)
+- No Playwright MCP server (browser automation disabled)
+- Features marked passing after lint/type-check succeeds
+- Faster iteration for prototyping
+
+**What's the same:**
+- Lint and type-check still run to verify code compiles
+- Feature MCP server for tracking progress
+- All other development tools available
+
+**When to use:** Early prototyping when you want to quickly scaffold features without verification overhead. Switch back to standard mode for production-quality development.
+
### React UI (in ui/ directory)
```bash
diff --git a/agent.py b/agent.py
index c7d3b22..7b6ef87 100644
--- a/agent.py
+++ b/agent.py
@@ -24,6 +24,7 @@ from progress import print_session_header, print_progress_summary, has_features
from prompts import (
get_initializer_prompt,
get_coding_prompt,
+ get_coding_prompt_yolo,
copy_spec_to_project,
has_project_prompts,
)
@@ -111,6 +112,7 @@ async def run_autonomous_agent(
project_dir: Path,
model: str,
max_iterations: Optional[int] = None,
+ yolo_mode: bool = False,
) -> None:
"""
Run the autonomous agent loop.
@@ -119,12 +121,17 @@ async def run_autonomous_agent(
project_dir: Directory for the project
model: Claude model to use
max_iterations: Maximum number of iterations (None for unlimited)
+ yolo_mode: If True, skip browser testing and use YOLO prompt
"""
print("\n" + "=" * 70)
print(" AUTONOMOUS CODING AGENT DEMO")
print("=" * 70)
print(f"\nProject directory: {project_dir}")
print(f"Model: {model}")
+ if yolo_mode:
+ print("Mode: YOLO (testing disabled)")
+ else:
+ print("Mode: Standard (full testing)")
if max_iterations:
print(f"Max iterations: {max_iterations}")
else:
@@ -170,7 +177,7 @@ async def run_autonomous_agent(
print_session_header(iteration, is_first_run)
# Create client (fresh context)
- client = create_client(project_dir, model)
+ client = create_client(project_dir, model, yolo_mode=yolo_mode)
# Choose prompt based on session type
# Pass project_dir to enable project-specific prompts
@@ -178,7 +185,11 @@ async def run_autonomous_agent(
prompt = get_initializer_prompt(project_dir)
is_first_run = False # Only use initializer once
else:
- prompt = get_coding_prompt(project_dir)
+ # Use YOLO prompt if in YOLO mode
+ if yolo_mode:
+ prompt = get_coding_prompt_yolo(project_dir)
+ else:
+ prompt = get_coding_prompt(project_dir)
# Run session with async context manager
async with client:
diff --git a/autonomous_agent_demo.py b/autonomous_agent_demo.py
index 0e9b2ee..caa2491 100644
--- a/autonomous_agent_demo.py
+++ b/autonomous_agent_demo.py
@@ -16,6 +16,9 @@ Example Usage:
# Limit iterations for testing
python autonomous_agent_demo.py --project-dir my-app --max-iterations 5
+
+ # YOLO mode: rapid prototyping without browser testing
+ python autonomous_agent_demo.py --project-dir my-app --yolo
"""
import argparse
@@ -57,6 +60,9 @@ Examples:
# Limit iterations for testing
python autonomous_agent_demo.py --project-dir my-app --max-iterations 5
+ # YOLO mode: rapid prototyping without browser testing
+ python autonomous_agent_demo.py --project-dir my-app --yolo
+
Authentication:
Uses Claude CLI credentials from ~/.claude/.credentials.json
Run 'claude login' to authenticate (handled by start.bat/start.sh)
@@ -84,6 +90,13 @@ Authentication:
help=f"Claude model to use (default: {DEFAULT_MODEL})",
)
+ parser.add_argument(
+ "--yolo",
+ action="store_true",
+ default=False,
+ help="Enable YOLO mode: rapid prototyping without browser testing",
+ )
+
return parser.parse_args()
@@ -122,6 +135,7 @@ def main() -> None:
project_dir=project_dir,
model=args.model,
max_iterations=args.max_iterations,
+ yolo_mode=args.yolo,
)
)
except KeyboardInterrupt:
diff --git a/client.py b/client.py
index 47d92f3..4c81160 100644
--- a/client.py
+++ b/client.py
@@ -72,13 +72,14 @@ BUILTIN_TOOLS = [
]
-def create_client(project_dir: Path, model: str):
+def create_client(project_dir: Path, model: str, yolo_mode: bool = False):
"""
Create a Claude Agent SDK client with multi-layered security.
Args:
project_dir: Directory for the project
model: Claude model to use
+ yolo_mode: If True, skip Playwright MCP server for rapid prototyping
Returns:
Configured ClaudeSDKClient (from claude_agent_sdk)
@@ -92,6 +93,30 @@ def create_client(project_dir: Path, model: str):
Note: Authentication is handled by start.bat/start.sh before this runs.
The Claude SDK auto-detects credentials from ~/.claude/.credentials.json
"""
+ # Build allowed tools list based on mode
+ # In YOLO mode, exclude Playwright tools for faster prototyping
+ allowed_tools = [*BUILTIN_TOOLS, *FEATURE_MCP_TOOLS]
+ if not yolo_mode:
+ allowed_tools.extend(PLAYWRIGHT_TOOLS)
+
+ # Build permissions list
+ permissions_list = [
+ # Allow all file operations within the project directory
+ "Read(./**)",
+ "Write(./**)",
+ "Edit(./**)",
+ "Glob(./**)",
+ "Grep(./**)",
+ # Bash permission granted here, but actual commands are validated
+ # by the bash_security_hook (see security.py for allowed commands)
+ "Bash(*)",
+ # Allow Feature MCP tools for feature management
+ *FEATURE_MCP_TOOLS,
+ ]
+ if not yolo_mode:
+ # Allow Playwright MCP tools for browser automation (standard mode only)
+ permissions_list.extend(PLAYWRIGHT_TOOLS)
+
# Create comprehensive security settings
# Note: Using relative paths ("./**") restricts access to project directory
# since cwd is set to project_dir
@@ -99,21 +124,7 @@ def create_client(project_dir: Path, model: str):
"sandbox": {"enabled": True, "autoAllowBashIfSandboxed": True},
"permissions": {
"defaultMode": "acceptEdits", # Auto-approve edits within allowed directories
- "allow": [
- # Allow all file operations within the project directory
- "Read(./**)",
- "Write(./**)",
- "Edit(./**)",
- "Glob(./**)",
- "Grep(./**)",
- # Bash permission granted here, but actual commands are validated
- # by the bash_security_hook (see security.py for allowed commands)
- "Bash(*)",
- # Allow Playwright MCP tools for browser automation
- *PLAYWRIGHT_TOOLS,
- # Allow Feature MCP tools for feature management
- *FEATURE_MCP_TOOLS,
- ],
+ "allow": permissions_list,
},
}
@@ -129,7 +140,10 @@ def create_client(project_dir: Path, model: str):
print(" - Sandbox enabled (OS-level bash isolation)")
print(f" - Filesystem restricted to: {project_dir.resolve()}")
print(" - Bash commands restricted to allowlist (see security.py)")
- print(" - MCP servers: playwright (browser), features (database)")
+ if yolo_mode:
+ print(" - MCP servers: features (database) - YOLO MODE (no Playwright)")
+ else:
+ print(" - MCP servers: playwright (browser), features (database)")
print(" - Project settings enabled (skills, commands, CLAUDE.md)")
print()
@@ -140,6 +154,27 @@ def create_client(project_dir: Path, model: str):
else:
print(" - Warning: System Claude CLI not found, using bundled CLI")
+ # Build MCP servers config - features is always included, playwright only in standard mode
+ mcp_servers = {
+ "features": {
+ "command": sys.executable, # Use the same Python that's running this script
+ "args": ["-m", "mcp_server.feature_mcp"],
+ "env": {
+ # Inherit parent environment (PATH, ANTHROPIC_API_KEY, etc.)
+ **os.environ,
+ # Add custom variables
+ "PROJECT_DIR": str(project_dir.resolve()),
+ "PYTHONPATH": str(Path(__file__).parent.resolve()),
+ },
+ },
+ }
+ if not yolo_mode:
+ # Include Playwright MCP server for browser automation (standard mode only)
+ mcp_servers["playwright"] = {
+ "command": "npx",
+ "args": ["@playwright/mcp@latest", "--viewport-size", "1280x720"],
+ }
+
return ClaudeSDKClient(
options=ClaudeAgentOptions(
model=model,
@@ -147,25 +182,8 @@ def create_client(project_dir: Path, model: str):
system_prompt="You are an expert full-stack developer building a production-quality web application.",
setting_sources=["project"], # Enable skills, commands, and CLAUDE.md from project dir
max_buffer_size=10 * 1024 * 1024, # 10MB for large Playwright screenshots
- allowed_tools=[
- *BUILTIN_TOOLS,
- *PLAYWRIGHT_TOOLS,
- *FEATURE_MCP_TOOLS,
- ],
- mcp_servers={
- "playwright": {"command": "npx", "args": ["@playwright/mcp@latest", "--viewport-size", "1280x720"]},
- "features": {
- "command": sys.executable, # Use the same Python that's running this script
- "args": ["-m", "mcp_server.feature_mcp"],
- "env": {
- # Inherit parent environment (PATH, ANTHROPIC_API_KEY, etc.)
- **os.environ,
- # Add custom variables
- "PROJECT_DIR": str(project_dir.resolve()),
- "PYTHONPATH": str(Path(__file__).parent.resolve()),
- },
- },
- },
+ allowed_tools=allowed_tools,
+ mcp_servers=mcp_servers,
hooks={
"PreToolUse": [
HookMatcher(matcher="Bash", hooks=[bash_security_hook]),
diff --git a/prompts.py b/prompts.py
index 7e666d0..85ebd81 100644
--- a/prompts.py
+++ b/prompts.py
@@ -75,6 +75,11 @@ def get_coding_prompt(project_dir: Path | None = None) -> str:
return load_prompt("coding_prompt", project_dir)
+def get_coding_prompt_yolo(project_dir: Path | None = None) -> str:
+ """Load the YOLO mode coding agent prompt (project-specific if available)."""
+ return load_prompt("coding_prompt_yolo", project_dir)
+
+
def get_app_spec(project_dir: Path) -> str:
"""
Load the app spec from the project.
@@ -131,6 +136,7 @@ def scaffold_project_prompts(project_dir: Path) -> Path:
templates = [
("app_spec.template.txt", "app_spec.txt"),
("coding_prompt.template.md", "coding_prompt.md"),
+ ("coding_prompt_yolo.template.md", "coding_prompt_yolo.md"),
("initializer_prompt.template.md", "initializer_prompt.md"),
]
diff --git a/server/routers/agent.py b/server/routers/agent.py
index 116adcf..ecce84c 100644
--- a/server/routers/agent.py
+++ b/server/routers/agent.py
@@ -11,7 +11,7 @@ from pathlib import Path
from fastapi import APIRouter, HTTPException
-from ..schemas import AgentStatus, AgentActionResponse
+from ..schemas import AgentStatus, AgentActionResponse, AgentStartRequest
from ..services.process_manager import get_manager
@@ -68,15 +68,19 @@ async def get_agent_status(project_name: str):
status=manager.status,
pid=manager.pid,
started_at=manager.started_at,
+ yolo_mode=manager.yolo_mode,
)
@router.post("/start", response_model=AgentActionResponse)
-async def start_agent(project_name: str):
+async def start_agent(
+ project_name: str,
+ request: AgentStartRequest = AgentStartRequest(),
+):
"""Start the agent for a project."""
manager = get_project_manager(project_name)
- success, message = await manager.start()
+ success, message = await manager.start(yolo_mode=request.yolo_mode)
return AgentActionResponse(
success=success,
diff --git a/server/schemas.py b/server/schemas.py
index 53bbad1..ab78080 100644
--- a/server/schemas.py
+++ b/server/schemas.py
@@ -99,11 +99,17 @@ class FeatureListResponse(BaseModel):
# Agent Schemas
# ============================================================================
+class AgentStartRequest(BaseModel):
+ """Request schema for starting the agent."""
+ yolo_mode: bool = False
+
+
class AgentStatus(BaseModel):
"""Current agent status."""
status: Literal["stopped", "running", "paused", "crashed"]
pid: int | None = None
started_at: datetime | None = None
+ yolo_mode: bool = False
class AgentActionResponse(BaseModel):
diff --git a/server/services/process_manager.py b/server/services/process_manager.py
index 6f78e24..31042cc 100644
--- a/server/services/process_manager.py
+++ b/server/services/process_manager.py
@@ -74,6 +74,7 @@ class AgentProcessManager:
self._status: Literal["stopped", "running", "paused", "crashed"] = "stopped"
self.started_at: datetime | None = None
self._output_task: asyncio.Task | None = None
+ self.yolo_mode: bool = False # YOLO mode for rapid prototyping
# Support multiple callbacks (for multiple WebSocket clients)
self._output_callbacks: Set[Callable[[str], Awaitable[None]]] = set()
@@ -214,10 +215,13 @@ class AgentProcessManager:
self.status = "stopped"
self._remove_lock()
- async def start(self) -> tuple[bool, str]:
+ async def start(self, yolo_mode: bool = False) -> tuple[bool, str]:
"""
Start the agent as a subprocess.
+ Args:
+ yolo_mode: If True, run in YOLO mode (no browser testing)
+
Returns:
Tuple of (success, message)
"""
@@ -227,6 +231,9 @@ class AgentProcessManager:
if not self._check_lock():
return False, "Another agent instance is already running for this project"
+ # Store YOLO mode for status queries
+ self.yolo_mode = yolo_mode
+
# Build command - pass absolute path to project directory
cmd = [
sys.executable,
@@ -235,6 +242,10 @@ class AgentProcessManager:
str(self.project_dir.resolve()),
]
+ # Add --yolo flag if YOLO mode is enabled
+ if yolo_mode:
+ cmd.append("--yolo")
+
try:
# Start subprocess with piped stdout/stderr
# Use project_dir as cwd so Claude SDK sandbox allows access to project files
@@ -295,6 +306,7 @@ class AgentProcessManager:
self.status = "stopped"
self.process = None
self.started_at = None
+ self.yolo_mode = False # Reset YOLO mode
return True, "Agent stopped"
except Exception as e:
@@ -375,6 +387,7 @@ class AgentProcessManager:
"status": self.status,
"pid": self.pid,
"started_at": self.started_at.isoformat() if self.started_at else None,
+ "yolo_mode": self.yolo_mode,
}
diff --git a/server/services/spec_chat_session.py b/server/services/spec_chat_session.py
index d762ac0..a1a55db 100644
--- a/server/services/spec_chat_session.py
+++ b/server/services/spec_chat_session.py
@@ -7,6 +7,7 @@ Uses the create-spec.md skill to guide users through app spec creation.
"""
import asyncio
+import json
import logging
import shutil
import threading
@@ -87,6 +88,33 @@ class SpecChatSession:
# Ensure project directory exists (like CLI does in start.py)
self.project_dir.mkdir(parents=True, exist_ok=True)
+ # Delete app_spec.txt so Claude can create it fresh
+ # The SDK requires reading existing files before writing, but app_spec.txt is created new
+ # Note: We keep initializer_prompt.md so Claude can read and update the template
+ prompts_dir = self.project_dir / "prompts"
+ app_spec_path = prompts_dir / "app_spec.txt"
+ if app_spec_path.exists():
+ app_spec_path.unlink()
+ logger.info("Deleted scaffolded app_spec.txt for fresh spec creation")
+
+ # Create security settings file (like client.py does)
+ # This grants permissions for file operations in the project directory
+ security_settings = {
+ "sandbox": {"enabled": False}, # Disable sandbox for spec creation
+ "permissions": {
+ "defaultMode": "acceptEdits",
+ "allow": [
+ "Read(./**)",
+ "Write(./**)",
+ "Edit(./**)",
+ "Glob(./**)",
+ ],
+ },
+ }
+ settings_file = self.project_dir / ".claude_settings.json"
+ with open(settings_file, "w") as f:
+ json.dump(security_settings, f, indent=2)
+
# Replace $ARGUMENTS with absolute project path (like CLI does in start.py:184)
# Using absolute path avoids confusion when project folder name differs from app name
project_path = str(self.project_dir.resolve())
@@ -111,6 +139,7 @@ class SpecChatSession:
permission_mode="acceptEdits", # Auto-approve file writes for spec creation
max_turns=100,
cwd=str(self.project_dir.resolve()),
+ settings=str(settings_file.resolve()),
)
)
# Enter the async context and track it
diff --git a/ui/src/App.tsx b/ui/src/App.tsx
index 4077755..3c639b6 100644
--- a/ui/src/App.tsx
+++ b/ui/src/App.tsx
@@ -1,5 +1,5 @@
import { useState, useEffect, useCallback } from 'react'
-import { useProjects, useFeatures } from './hooks/useProjects'
+import { useProjects, useFeatures, useAgentStatus } from './hooks/useProjects'
import { useProjectWebSocket } from './hooks/useWebSocket'
import { useFeatureSound } from './hooks/useFeatureSound'
import { useCelebration } from './hooks/useCelebration'
@@ -34,6 +34,7 @@ function App() {
const { data: projects, isLoading: projectsLoading } = useProjects()
const { data: features } = useFeatures(selectedProject)
+ const { data: agentStatusData } = useAgentStatus(selectedProject)
const wsState = useProjectWebSocket(selectedProject)
// Play sounds when features move between columns
@@ -151,6 +152,7 @@ function App() {