Cleanup and some docs
108
README.md
|
|
@ -45,6 +45,7 @@ You work with Claude Code on a feature, close the terminal, come back tomorrow..
|
||||||
### Key Features
|
### Key Features
|
||||||
|
|
||||||
✅ **Lightning-Fast Indexing** - NEW! Tree-sitter hybrid indexing: 10,000 files in 30 seconds (vs 3-5 hours)
|
✅ **Lightning-Fast Indexing** - NEW! Tree-sitter hybrid indexing: 10,000 files in 30 seconds (vs 3-5 hours)
|
||||||
|
✅ **Real-Time Kanban Board** - NEW! Auto-syncing task visualization for agent-os specs (updates within 3 seconds)
|
||||||
✅ **One-Command Project Init** - `/claude-os-init` and you're done
|
✅ **One-Command Project Init** - `/claude-os-init` and you're done
|
||||||
✅ **Automatic Context Loading** - Starts every session with relevant memories
|
✅ **Automatic Context Loading** - Starts every session with relevant memories
|
||||||
✅ **Session Management** - Track work, save progress, resume later
|
✅ **Session Management** - Track work, save progress, resume later
|
||||||
|
|
@ -100,6 +101,53 @@ Inspired by [Aider's](https://github.com/Aider-AI/aider) approach, Claude OS now
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
## 🎨 Visual Interface
|
||||||
|
|
||||||
|
**Claude OS provides a beautiful, intuitive web interface for managing your AI development workflow:**
|
||||||
|
|
||||||
|
<table>
|
||||||
|
<tr>
|
||||||
|
<td width="50%">
|
||||||
|
|
||||||
|
### Welcome Screen
|
||||||
|
|
||||||
|

|
||||||
|
Get started with Claude OS
|
||||||
|
|
||||||
|
</td>
|
||||||
|
<td width="50%">
|
||||||
|
|
||||||
|
### Project Overview
|
||||||
|
|
||||||
|

|
||||||
|
View project details and MCP status
|
||||||
|
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td width="50%">
|
||||||
|
|
||||||
|
### Kanban Board
|
||||||
|
|
||||||
|

|
||||||
|
Track spec implementation progress
|
||||||
|
|
||||||
|
</td>
|
||||||
|
<td width="50%">
|
||||||
|
|
||||||
|
### Services Dashboard
|
||||||
|
|
||||||
|

|
||||||
|
Monitor all Claude OS services
|
||||||
|
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
**📖 See the complete visual guide:** [docs/guides/VISUAL_GUIDE.md](docs/guides/VISUAL_GUIDE.md)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## 🏗️ Architecture Overview
|
## 🏗️ Architecture Overview
|
||||||
|
|
||||||
<p align="center">
|
<p align="center">
|
||||||
|
|
@ -415,7 +463,6 @@ your-project/
|
||||||
└── .claude/agents/agent-os/ # 8 agents (symlinked)
|
└── .claude/agents/agent-os/ # 8 agents (symlinked)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
### Integration with Claude OS
|
### Integration with Claude OS
|
||||||
|
|
||||||
Agent-OS agents deeply integrate with Claude OS:
|
Agent-OS agents deeply integrate with Claude OS:
|
||||||
|
|
@ -431,7 +478,10 @@ Agent-OS agents deeply integrate with Claude OS:
|
||||||
|
|
||||||
## 🎯 Spec Tracking & Kanban Board
|
## 🎯 Spec Tracking & Kanban Board
|
||||||
|
|
||||||
**Claude OS now automatically tracks your Agent-OS specs and displays them as an interactive Kanban board!**
|
**NEW: Real-time auto-syncing Kanban board for Agent-OS specs!**
|
||||||
|
|
||||||
|

|
||||||
|
*Visual Kanban board showing specs, tasks, and progress tracking*
|
||||||
|
|
||||||
### What It Does
|
### What It Does
|
||||||
|
|
||||||
|
|
@ -440,17 +490,31 @@ When you use Agent-OS to create specs with `/create-spec`, Claude OS automatical
|
||||||
- 📋 **Parses tasks.md files** - Extracts all tasks, phases, dependencies, and metadata
|
- 📋 **Parses tasks.md files** - Extracts all tasks, phases, dependencies, and metadata
|
||||||
- 🗄️ **Stores in database** - Tracks progress, completion, and time estimates
|
- 🗄️ **Stores in database** - Tracks progress, completion, and time estimates
|
||||||
- 📊 **Displays as Kanban** - Visual board showing specs and tasks by status
|
- 📊 **Displays as Kanban** - Visual board showing specs and tasks by status
|
||||||
- ✅ **Updates in real-time** - Task status changes are reflected immediately
|
- ⚡ **Real-time sync** - NEW! Auto-detects file changes and updates within 3 seconds
|
||||||
|
- 👀 **File watching** - Monitors `agent-os/specs/` folder for changes
|
||||||
|
- ✅ **Auto-refresh** - Board polls every 3 seconds for live updates
|
||||||
- 🗃️ **Archives completed specs** - Keep your board focused on active work
|
- 🗃️ **Archives completed specs** - Keep your board focused on active work
|
||||||
|
|
||||||
### Features
|
### Features
|
||||||
|
|
||||||
|
**Real-Time File Watching (NEW!):**
|
||||||
|
|
||||||
|
- Automatically monitors your `agent-os/specs/` folder
|
||||||
|
- Detects changes to `tasks.md` and `spec.md` files
|
||||||
|
- 2-second debounce to batch rapid edits
|
||||||
|
- Auto-syncs to database within 3 seconds
|
||||||
|
- Frontend auto-refreshes every 3 seconds
|
||||||
|
- **Total latency: ~6 seconds from file save to board update**
|
||||||
|
|
||||||
**Automatic Syncing:**
|
**Automatic Syncing:**
|
||||||
|
|
||||||
- Syncs all specs from your project's `agent-os/specs/` folder
|
- Syncs all specs from your project's `agent-os/specs/` folder
|
||||||
- Tracks task metadata (estimated time, dependencies, risk level)
|
- Tracks task metadata (estimated time, dependencies, risk level)
|
||||||
- Auto-detects completed tasks (marked with ✅ in tasks.md)
|
- Auto-detects completed tasks (marked with ✅ or `[x]` in tasks.md)
|
||||||
|
- Supports both checkbox format and classic format
|
||||||
|
|
||||||
**Progress Tracking:**
|
**Progress Tracking:**
|
||||||
|
|
||||||
- **Status auto-updates** based on completion:
|
- **Status auto-updates** based on completion:
|
||||||
- `planning` - No tasks completed yet
|
- `planning` - No tasks completed yet
|
||||||
- `in_progress` - Some tasks completed
|
- `in_progress` - Some tasks completed
|
||||||
|
|
@ -459,6 +523,7 @@ When you use Agent-OS to create specs with `/create-spec`, Claude OS automatical
|
||||||
- Time estimates tracked (estimated vs actual minutes)
|
- Time estimates tracked (estimated vs actual minutes)
|
||||||
|
|
||||||
**Archive Feature:**
|
**Archive Feature:**
|
||||||
|
|
||||||
- Archive completed specs to keep your board clean
|
- Archive completed specs to keep your board clean
|
||||||
- Archived specs hidden by default but can be viewed
|
- Archived specs hidden by default but can be viewed
|
||||||
- Preserves all task history for future reference
|
- Preserves all task history for future reference
|
||||||
|
|
@ -481,7 +546,7 @@ PATCH /api/tasks/{task_id}/status
|
||||||
"actual_minutes": 15
|
"actual_minutes": 15
|
||||||
}
|
}
|
||||||
|
|
||||||
# Sync specs from agent-os folder
|
# Sync specs from agent-os folder (manual)
|
||||||
POST /api/projects/{project_id}/specs/sync
|
POST /api/projects/{project_id}/specs/sync
|
||||||
|
|
||||||
# Get Kanban board view
|
# Get Kanban board view
|
||||||
|
|
@ -490,30 +555,46 @@ GET /api/projects/{project_id}/kanban?include_archived=false
|
||||||
# Archive/unarchive specs
|
# Archive/unarchive specs
|
||||||
POST /api/specs/{spec_id}/archive
|
POST /api/specs/{spec_id}/archive
|
||||||
POST /api/specs/{spec_id}/unarchive
|
POST /api/specs/{spec_id}/unarchive
|
||||||
|
|
||||||
|
# NEW: Real-time spec watcher control
|
||||||
|
GET /api/spec-watcher/status
|
||||||
|
POST /api/spec-watcher/start/{project_id}
|
||||||
|
POST /api/spec-watcher/stop/{project_id}
|
||||||
|
POST /api/spec-watcher/start-all
|
||||||
```
|
```
|
||||||
|
|
||||||
|
**See:** `docs/guides/REALTIME_KANBAN_GUIDE.md` for complete documentation.
|
||||||
|
|
||||||
### How It Works
|
### How It Works
|
||||||
|
|
||||||
```
|
```
|
||||||
1. You create a spec with Agent-OS:
|
1. You create a spec with Agent-OS:
|
||||||
/create-spec → agent-os/specs/2025-01-15-user-auth/
|
/create-spec → agent-os/specs/2025-01-15-user-auth/
|
||||||
|
|
||||||
2. Claude OS discovers and parses it:
|
2. Spec Watcher detects the new folder:
|
||||||
|
- Auto-starts when MCP server boots
|
||||||
|
- Monitors agent-os/specs/ directory
|
||||||
|
- 2-second debounce for batch changes
|
||||||
|
|
||||||
|
3. Auto-sync to database:
|
||||||
- Reads tasks.md
|
- Reads tasks.md
|
||||||
|
- Parses checkbox format: - [x] Task title
|
||||||
- Extracts metadata, tasks, phases
|
- Extracts metadata, tasks, phases
|
||||||
- Stores in SQLite database
|
- Stores in SQLite database
|
||||||
|
- ✅ Completes within 3 seconds
|
||||||
|
|
||||||
3. View in Kanban board:
|
4. View in Kanban board (auto-refreshes every 3 seconds):
|
||||||
- Todo: PHASE1-TASK1, PHASE1-TASK2
|
- Todo: PHASE1-TASK1, PHASE1-TASK2
|
||||||
- In Progress: PHASE2-TASK1
|
- In Progress: PHASE2-TASK1
|
||||||
- Done: PHASE1-TASK3, PHASE1-TASK4
|
- Done: PHASE1-TASK3, PHASE1-TASK4
|
||||||
|
|
||||||
4. Track progress as you work:
|
5. As you work, agent-os updates tasks.md:
|
||||||
- Update task status via API
|
- File watcher detects change
|
||||||
- Spec status auto-updates
|
- Auto-syncs to database
|
||||||
- Progress percentage calculated
|
- Board refreshes automatically
|
||||||
|
- Total latency: ~6 seconds
|
||||||
|
|
||||||
5. Archive when complete:
|
6. Archive when complete:
|
||||||
- Mark spec as archived
|
- Mark spec as archived
|
||||||
- Keeps history but cleans up board
|
- Keeps history but cleans up board
|
||||||
```
|
```
|
||||||
|
|
@ -523,12 +604,14 @@ POST /api/specs/{spec_id}/unarchive
|
||||||
Two new tables track specs and tasks:
|
Two new tables track specs and tasks:
|
||||||
|
|
||||||
**`specs` table:**
|
**`specs` table:**
|
||||||
|
|
||||||
- Stores spec metadata (name, path, status)
|
- Stores spec metadata (name, path, status)
|
||||||
- Tracks total/completed tasks
|
- Tracks total/completed tasks
|
||||||
- Calculates progress percentage
|
- Calculates progress percentage
|
||||||
- Archive flag to hide completed specs
|
- Archive flag to hide completed specs
|
||||||
|
|
||||||
**`spec_tasks` table:**
|
**`spec_tasks` table:**
|
||||||
|
|
||||||
- Individual tasks with codes (PHASE1-TASK1)
|
- Individual tasks with codes (PHASE1-TASK1)
|
||||||
- Status (todo/in_progress/done/blocked)
|
- Status (todo/in_progress/done/blocked)
|
||||||
- Time tracking (estimated vs actual)
|
- Time tracking (estimated vs actual)
|
||||||
|
|
@ -902,6 +985,7 @@ claude-os/
|
||||||
|
|
||||||
### Core Features
|
### Core Features
|
||||||
|
|
||||||
|
- **[docs/guides/REALTIME_KANBAN_GUIDE.md](docs/guides/REALTIME_KANBAN_GUIDE.md)** - ⚡ **NEW! Real-time Kanban board** (auto-sync, file watching, API reference)
|
||||||
- **[docs/SELF_LEARNING_SYSTEM.md](docs/SELF_LEARNING_SYSTEM.md)** - 🧠 How Claude learns automatically
|
- **[docs/SELF_LEARNING_SYSTEM.md](docs/SELF_LEARNING_SYSTEM.md)** - 🧠 How Claude learns automatically
|
||||||
- **[docs/REAL_TIME_LEARNING_GUIDE.md](docs/REAL_TIME_LEARNING_GUIDE.md)** - Real-time learning usage
|
- **[docs/REAL_TIME_LEARNING_GUIDE.md](docs/REAL_TIME_LEARNING_GUIDE.md)** - Real-time learning usage
|
||||||
- **[docs/MEMORY_MCP_GUIDE.md](docs/MEMORY_MCP_GUIDE.md)** - Persistent memory guide
|
- **[docs/MEMORY_MCP_GUIDE.md](docs/MEMORY_MCP_GUIDE.md)** - Persistent memory guide
|
||||||
|
|
|
||||||
|
|
@ -84,17 +84,21 @@ class TasksParser:
|
||||||
"""Parse all tasks from the markdown."""
|
"""Parse all tasks from the markdown."""
|
||||||
tasks = []
|
tasks = []
|
||||||
|
|
||||||
# Find all task sections (e.g., ### PHASE1-TASK1:)
|
# Try original format first (### PHASE1-TASK1:)
|
||||||
task_pattern = r'###\s+(PHASE\d+-TASK\d+):\s*(.+?)(?=###|\Z)'
|
task_pattern = r'###\s+(PHASE\d+-TASK\d+):\s*(.+?)(?=###|\Z)'
|
||||||
matches = re.finditer(task_pattern, self.content, re.DOTALL)
|
matches = list(re.finditer(task_pattern, self.content, re.DOTALL))
|
||||||
|
|
||||||
for match in matches:
|
if matches:
|
||||||
task_code = match.group(1)
|
# Original format found
|
||||||
task_content = match.group(2)
|
for match in matches:
|
||||||
|
task_code = match.group(1)
|
||||||
task = self._parse_single_task(task_code, task_content)
|
task_content = match.group(2)
|
||||||
if task:
|
task = self._parse_single_task(task_code, task_content)
|
||||||
tasks.append(task)
|
if task:
|
||||||
|
tasks.append(task)
|
||||||
|
else:
|
||||||
|
# Try checkbox format (- [ ] or - [x])
|
||||||
|
tasks = self._parse_checkbox_tasks()
|
||||||
|
|
||||||
return tasks
|
return tasks
|
||||||
|
|
||||||
|
|
@ -178,6 +182,58 @@ class TasksParser:
|
||||||
|
|
||||||
return 0 # Default if can't parse
|
return 0 # Default if can't parse
|
||||||
|
|
||||||
|
def _parse_checkbox_tasks(self) -> List[Dict]:
|
||||||
|
"""Parse tasks in checkbox format (- [ ] or - [x])."""
|
||||||
|
tasks = []
|
||||||
|
current_phase = "Phase 1"
|
||||||
|
task_counter = 1
|
||||||
|
|
||||||
|
# Match checkbox lines: - [ ] or - [x] followed by task code and title
|
||||||
|
# Examples:
|
||||||
|
# - [x] 1.0 Complete database layer
|
||||||
|
# - [ ] 2.1 Write 2-8 focused tests
|
||||||
|
checkbox_pattern = r'^[\s]*-\s+\[([ x])\]\s+(\d+\.\d+)\s+(.+?)$'
|
||||||
|
|
||||||
|
lines = self.content.split('\n')
|
||||||
|
for i, line in enumerate(lines):
|
||||||
|
match = re.match(checkbox_pattern, line)
|
||||||
|
if match:
|
||||||
|
is_checked = match.group(1) == 'x'
|
||||||
|
task_number = match.group(2)
|
||||||
|
title = match.group(3).strip()
|
||||||
|
|
||||||
|
# Determine phase from task number (1.x = Phase 1, 2.x = Phase 2, etc.)
|
||||||
|
phase_num = int(task_number.split('.')[0])
|
||||||
|
current_phase = f"Phase {phase_num}"
|
||||||
|
|
||||||
|
# Extract additional details from following indented lines
|
||||||
|
description_lines = []
|
||||||
|
j = i + 1
|
||||||
|
while j < len(lines) and (lines[j].startswith(' ') or lines[j].startswith('\t')):
|
||||||
|
desc_line = lines[j].strip()
|
||||||
|
if desc_line and not desc_line.startswith('- ['):
|
||||||
|
description_lines.append(desc_line)
|
||||||
|
j += 1
|
||||||
|
|
||||||
|
description = ' '.join(description_lines) if description_lines else ''
|
||||||
|
|
||||||
|
# Build task
|
||||||
|
task = {
|
||||||
|
'task_code': f'PHASE{phase_num}-TASK{task_counter}',
|
||||||
|
'phase': current_phase,
|
||||||
|
'title': title,
|
||||||
|
'description': description[:500] if description else '', # Limit description length
|
||||||
|
'estimated_minutes': 60, # Default 1 hour
|
||||||
|
'risk_level': 'medium', # Default medium risk
|
||||||
|
'dependencies': [],
|
||||||
|
'status': 'done' if is_checked else 'todo'
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.append(task)
|
||||||
|
task_counter += 1
|
||||||
|
|
||||||
|
return tasks
|
||||||
|
|
||||||
|
|
||||||
def find_spec_folders(project_path: str) -> List[str]:
|
def find_spec_folders(project_path: str) -> List[str]:
|
||||||
"""Find all spec folders in a project's agent-os directory."""
|
"""Find all spec folders in a project's agent-os directory."""
|
||||||
|
|
|
||||||
270
app/core/spec_watcher.py
Normal file
|
|
@ -0,0 +1,270 @@
|
||||||
|
"""
|
||||||
|
File system watcher for agent-os specs.
|
||||||
|
Automatically syncs specs to database when tasks.md files change.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
import logging
|
||||||
|
import threading
|
||||||
|
from pathlib import Path
|
||||||
|
from typing import Dict, Optional, List
|
||||||
|
from watchdog.observers import Observer
|
||||||
|
from watchdog.events import FileSystemEventHandler, FileModifiedEvent, FileCreatedEvent
|
||||||
|
|
||||||
|
from app.core.spec_manager import SpecManager
|
||||||
|
from app.core.spec_parser import parse_spec_folder
|
||||||
|
from app.core.sqlite_manager import get_sqlite_manager
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
class SpecFileHandler(FileSystemEventHandler):
|
||||||
|
"""Handles file system events for agent-os specs."""
|
||||||
|
|
||||||
|
def __init__(self, project_id: int, project_path: str):
|
||||||
|
"""
|
||||||
|
Initialize spec file handler.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
project_id: ID of the project
|
||||||
|
project_path: Path to the project root
|
||||||
|
"""
|
||||||
|
self.project_id = project_id
|
||||||
|
self.project_path = project_path
|
||||||
|
self.spec_manager = SpecManager()
|
||||||
|
self.debounce_timers: Dict[str, threading.Timer] = {}
|
||||||
|
self.debounce_delay = 2.0 # Debounce for 2 seconds
|
||||||
|
|
||||||
|
def on_modified(self, event: FileModifiedEvent):
|
||||||
|
"""Handle file modifications."""
|
||||||
|
if event.is_directory:
|
||||||
|
return
|
||||||
|
|
||||||
|
# Only react to tasks.md or spec.md changes
|
||||||
|
filename = Path(event.src_path).name
|
||||||
|
if filename not in ['tasks.md', 'spec.md']:
|
||||||
|
return
|
||||||
|
|
||||||
|
self._debounce_sync(event.src_path)
|
||||||
|
|
||||||
|
def on_created(self, event: FileCreatedEvent):
|
||||||
|
"""Handle file creation."""
|
||||||
|
if event.is_directory:
|
||||||
|
# New spec folder created - sync entire project
|
||||||
|
self._debounce_sync_all()
|
||||||
|
return
|
||||||
|
|
||||||
|
# Only react to tasks.md or spec.md
|
||||||
|
filename = Path(event.src_path).name
|
||||||
|
if filename not in ['tasks.md', 'spec.md']:
|
||||||
|
return
|
||||||
|
|
||||||
|
self._debounce_sync(event.src_path)
|
||||||
|
|
||||||
|
def _debounce_sync(self, file_path: str):
|
||||||
|
"""Debounce sync calls to avoid multiple rapid syncs."""
|
||||||
|
# Get the spec folder (parent of tasks.md)
|
||||||
|
spec_folder = str(Path(file_path).parent)
|
||||||
|
|
||||||
|
# Cancel previous timer if it exists
|
||||||
|
if spec_folder in self.debounce_timers:
|
||||||
|
self.debounce_timers[spec_folder].cancel()
|
||||||
|
|
||||||
|
# Create new timer
|
||||||
|
timer = threading.Timer(
|
||||||
|
self.debounce_delay,
|
||||||
|
lambda: self._trigger_sync(spec_folder)
|
||||||
|
)
|
||||||
|
self.debounce_timers[spec_folder] = timer
|
||||||
|
timer.start()
|
||||||
|
|
||||||
|
def _debounce_sync_all(self):
|
||||||
|
"""Debounce full project sync."""
|
||||||
|
key = "__all__"
|
||||||
|
|
||||||
|
# Cancel previous timer if it exists
|
||||||
|
if key in self.debounce_timers:
|
||||||
|
self.debounce_timers[key].cancel()
|
||||||
|
|
||||||
|
# Create new timer
|
||||||
|
timer = threading.Timer(
|
||||||
|
self.debounce_delay,
|
||||||
|
self._trigger_sync_all
|
||||||
|
)
|
||||||
|
self.debounce_timers[key] = timer
|
||||||
|
timer.start()
|
||||||
|
|
||||||
|
def _trigger_sync(self, spec_folder: str):
|
||||||
|
"""Trigger sync for a specific spec."""
|
||||||
|
try:
|
||||||
|
spec_name = Path(spec_folder).name
|
||||||
|
logger.info(f"Syncing spec: {spec_name} for project {self.project_id}")
|
||||||
|
|
||||||
|
# Parse the spec
|
||||||
|
spec_data = parse_spec_folder(spec_folder)
|
||||||
|
if not spec_data:
|
||||||
|
logger.warning(f"Failed to parse spec folder: {spec_folder}")
|
||||||
|
return
|
||||||
|
|
||||||
|
# Sync to database
|
||||||
|
result = self.spec_manager.create_or_update_spec(self.project_id, spec_data)
|
||||||
|
|
||||||
|
action = "Updated" if not result['created'] else "Created"
|
||||||
|
task_count = len(spec_data['tasks'])
|
||||||
|
logger.info(f"✅ {action} spec '{spec_data['name']}' with {task_count} tasks")
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Error syncing spec {spec_folder}: {e}", exc_info=True)
|
||||||
|
|
||||||
|
def _trigger_sync_all(self):
|
||||||
|
"""Trigger sync for all specs in project."""
|
||||||
|
try:
|
||||||
|
logger.info(f"Syncing all specs for project {self.project_id}")
|
||||||
|
result = self.spec_manager.sync_project_specs(self.project_id, self.project_path)
|
||||||
|
logger.info(f"✅ Synced {result['synced']} new, updated {result['updated']} existing specs")
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Error syncing all specs: {e}", exc_info=True)
|
||||||
|
|
||||||
|
|
||||||
|
class SpecWatcher:
|
||||||
|
"""Watches agent-os specs folder for a project."""
|
||||||
|
|
||||||
|
def __init__(self, project_id: int, project_path: str):
|
||||||
|
"""
|
||||||
|
Initialize spec watcher.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
project_id: ID of the project
|
||||||
|
project_path: Path to the project root
|
||||||
|
"""
|
||||||
|
self.project_id = project_id
|
||||||
|
self.project_path = project_path
|
||||||
|
self.specs_path = Path(project_path) / "agent-os" / "specs"
|
||||||
|
self.observer: Optional[Observer] = None
|
||||||
|
self.event_handler: Optional[SpecFileHandler] = None
|
||||||
|
|
||||||
|
def start(self):
|
||||||
|
"""Start watching specs folder."""
|
||||||
|
if not self.specs_path.exists():
|
||||||
|
logger.warning(f"Specs folder does not exist: {self.specs_path}")
|
||||||
|
logger.info(f"Creating specs folder: {self.specs_path}")
|
||||||
|
self.specs_path.mkdir(parents=True, exist_ok=True)
|
||||||
|
return
|
||||||
|
|
||||||
|
logger.info(f"Starting spec watcher for project {self.project_id}")
|
||||||
|
logger.info(f"Watching: {self.specs_path}")
|
||||||
|
|
||||||
|
# Create observer
|
||||||
|
self.observer = Observer()
|
||||||
|
|
||||||
|
# Create event handler
|
||||||
|
self.event_handler = SpecFileHandler(self.project_id, self.project_path)
|
||||||
|
|
||||||
|
# Schedule observer
|
||||||
|
self.observer.schedule(self.event_handler, str(self.specs_path), recursive=True)
|
||||||
|
self.observer.start()
|
||||||
|
|
||||||
|
logger.info(f"✅ Spec watcher started for project {self.project_id}")
|
||||||
|
|
||||||
|
def stop(self):
|
||||||
|
"""Stop watching specs folder."""
|
||||||
|
if self.observer:
|
||||||
|
self.observer.stop()
|
||||||
|
self.observer.join()
|
||||||
|
logger.info(f"Spec watcher stopped for project {self.project_id}")
|
||||||
|
self.observer = None
|
||||||
|
self.event_handler = None
|
||||||
|
|
||||||
|
def restart(self):
|
||||||
|
"""Restart watcher."""
|
||||||
|
self.stop()
|
||||||
|
self.start()
|
||||||
|
|
||||||
|
|
||||||
|
class GlobalSpecWatcher:
|
||||||
|
"""Manages spec watchers for all projects."""
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
"""Initialize global spec watcher."""
|
||||||
|
self.watchers: Dict[int, SpecWatcher] = {}
|
||||||
|
self.lock = threading.Lock()
|
||||||
|
|
||||||
|
def start_project(self, project_id: int, project_path: str):
|
||||||
|
"""Start watching a project's specs."""
|
||||||
|
with self.lock:
|
||||||
|
if project_id in self.watchers:
|
||||||
|
logger.info(f"Spec watcher already exists for project {project_id}, restarting...")
|
||||||
|
self.watchers[project_id].restart()
|
||||||
|
return
|
||||||
|
|
||||||
|
watcher = SpecWatcher(project_id, project_path)
|
||||||
|
watcher.start()
|
||||||
|
self.watchers[project_id] = watcher
|
||||||
|
|
||||||
|
def stop_project(self, project_id: int):
|
||||||
|
"""Stop watching a project's specs."""
|
||||||
|
with self.lock:
|
||||||
|
if project_id not in self.watchers:
|
||||||
|
return
|
||||||
|
|
||||||
|
watcher = self.watchers.pop(project_id)
|
||||||
|
watcher.stop()
|
||||||
|
|
||||||
|
def restart_project(self, project_id: int):
|
||||||
|
"""Restart watcher for a project."""
|
||||||
|
with self.lock:
|
||||||
|
if project_id in self.watchers:
|
||||||
|
self.watchers[project_id].restart()
|
||||||
|
|
||||||
|
def start_all(self):
|
||||||
|
"""Start watching all projects."""
|
||||||
|
# Get all projects from database
|
||||||
|
db_manager = get_sqlite_manager()
|
||||||
|
projects = db_manager.list_projects()
|
||||||
|
|
||||||
|
logger.info(f"Starting spec watchers for {len(projects)} projects")
|
||||||
|
|
||||||
|
for project in projects:
|
||||||
|
try:
|
||||||
|
self.start_project(project['id'], project['path'])
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Error starting spec watcher for project {project['id']}: {e}")
|
||||||
|
|
||||||
|
def stop_all(self):
|
||||||
|
"""Stop watching all projects."""
|
||||||
|
with self.lock:
|
||||||
|
for watcher in self.watchers.values():
|
||||||
|
try:
|
||||||
|
watcher.stop()
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Error stopping spec watcher: {e}")
|
||||||
|
|
||||||
|
self.watchers.clear()
|
||||||
|
|
||||||
|
def get_status(self) -> Dict:
|
||||||
|
"""Get status of all spec watchers."""
|
||||||
|
with self.lock:
|
||||||
|
return {
|
||||||
|
"enabled": len(self.watchers) > 0,
|
||||||
|
"projects_watched": len(self.watchers),
|
||||||
|
"projects": {
|
||||||
|
project_id: {
|
||||||
|
"project_path": watcher.project_path,
|
||||||
|
"specs_path": str(watcher.specs_path),
|
||||||
|
"watching": watcher.observer is not None
|
||||||
|
}
|
||||||
|
for project_id, watcher in self.watchers.items()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# Global instance
|
||||||
|
_global_spec_watcher: Optional[GlobalSpecWatcher] = None
|
||||||
|
|
||||||
|
|
||||||
|
def get_global_spec_watcher() -> GlobalSpecWatcher:
|
||||||
|
"""Get or create global spec watcher."""
|
||||||
|
global _global_spec_watcher
|
||||||
|
if _global_spec_watcher is None:
|
||||||
|
_global_spec_watcher = GlobalSpecWatcher()
|
||||||
|
return _global_spec_watcher
|
||||||
|
|
@ -11,11 +11,13 @@ Complete reference for all Claude OS MCP Server API endpoints.
|
||||||
1. [Knowledge Base Operations](#knowledge-base-operations)
|
1. [Knowledge Base Operations](#knowledge-base-operations)
|
||||||
2. [Hybrid Indexing](#hybrid-indexing-new)
|
2. [Hybrid Indexing](#hybrid-indexing-new)
|
||||||
3. [Project Management](#project-management)
|
3. [Project Management](#project-management)
|
||||||
4. [Hooks System](#hooks-system)
|
4. [Agent-OS Spec Tracking](#agent-os-spec-tracking-new)
|
||||||
5. [File Watcher](#file-watcher)
|
5. [Real-Time Spec Watcher](#real-time-spec-watcher-new)
|
||||||
6. [Authentication](#authentication)
|
6. [Hooks System](#hooks-system)
|
||||||
7. [Utilities](#utilities)
|
7. [File Watcher](#file-watcher)
|
||||||
8. [Health Check](#health-check)
|
8. [Authentication](#authentication)
|
||||||
|
9. [Utilities](#utilities)
|
||||||
|
10. [Health Check](#health-check)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
@ -493,6 +495,218 @@ DELETE /api/projects/{id}
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
## Agent-OS Spec Tracking (NEW)
|
||||||
|
|
||||||
|
Real-time tracking and visualization of agent-os specifications and tasks through the Kanban board.
|
||||||
|
|
||||||
|
### Get Project Kanban Board
|
||||||
|
```http
|
||||||
|
GET /api/projects/{id}/kanban?include_archived=false
|
||||||
|
```
|
||||||
|
|
||||||
|
Returns complete Kanban view with all specs and tasks grouped by status.
|
||||||
|
|
||||||
|
**Response:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"project_id": 1,
|
||||||
|
"specs": [
|
||||||
|
{
|
||||||
|
"id": 1,
|
||||||
|
"name": "Manual Appointment Times",
|
||||||
|
"slug": "manual-appointment-times",
|
||||||
|
"folder_name": "2025-10-29-manual-appointment-times",
|
||||||
|
"path": "/path/to/project/agent-os/specs/2025-10-29-manual-appointment-times",
|
||||||
|
"total_tasks": 71,
|
||||||
|
"completed_tasks": 43,
|
||||||
|
"status": "in_progress",
|
||||||
|
"progress": 60.6,
|
||||||
|
"archived": false,
|
||||||
|
"tasks": {
|
||||||
|
"todo": [...],
|
||||||
|
"in_progress": [...],
|
||||||
|
"done": [...],
|
||||||
|
"blocked": [...]
|
||||||
|
},
|
||||||
|
"task_count_by_status": {
|
||||||
|
"todo": 28,
|
||||||
|
"in_progress": 0,
|
||||||
|
"done": 43,
|
||||||
|
"blocked": 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"summary": {
|
||||||
|
"total_specs": 3,
|
||||||
|
"total_tasks": 123,
|
||||||
|
"completed_tasks": 56
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Sync Project Specs
|
||||||
|
```http
|
||||||
|
POST /api/projects/{id}/specs/sync
|
||||||
|
```
|
||||||
|
|
||||||
|
Manually trigger sync of all spec files from `agent-os/specs/` folder to database.
|
||||||
|
|
||||||
|
**Response:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"project_id": 1,
|
||||||
|
"message": "Specs synced successfully",
|
||||||
|
"synced": 0,
|
||||||
|
"updated": 3,
|
||||||
|
"total": 3,
|
||||||
|
"errors": []
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Get Spec Tasks
|
||||||
|
```http
|
||||||
|
GET /api/specs/{spec_id}/tasks
|
||||||
|
```
|
||||||
|
|
||||||
|
Returns all tasks for a specific spec.
|
||||||
|
|
||||||
|
**Response:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"spec_id": 1,
|
||||||
|
"tasks": [
|
||||||
|
{
|
||||||
|
"id": 53,
|
||||||
|
"task_code": "PHASE1-TASK1",
|
||||||
|
"phase": "Phase 1",
|
||||||
|
"title": "Complete database layer",
|
||||||
|
"description": "Implement all database models and migrations",
|
||||||
|
"status": "done",
|
||||||
|
"estimated_minutes": 60,
|
||||||
|
"actual_minutes": 120,
|
||||||
|
"risk_level": "medium",
|
||||||
|
"dependencies": [],
|
||||||
|
"started_at": "2025-10-29T10:00:00Z",
|
||||||
|
"completed_at": "2025-10-29T12:00:00Z"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Update Task Status
|
||||||
|
```http
|
||||||
|
PATCH /api/tasks/{task_id}/status
|
||||||
|
Content-Type: application/json
|
||||||
|
|
||||||
|
{
|
||||||
|
"status": "in_progress",
|
||||||
|
"actual_minutes": 90
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Valid Statuses:**
|
||||||
|
- `todo` - Not started
|
||||||
|
- `in_progress` - Currently working
|
||||||
|
- `done` - Completed
|
||||||
|
- `blocked` - Waiting on dependencies
|
||||||
|
|
||||||
|
**Response:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"success": true,
|
||||||
|
"old_status": "todo",
|
||||||
|
"new_status": "in_progress"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Archive Spec
|
||||||
|
```http
|
||||||
|
POST /api/specs/{spec_id}/archive
|
||||||
|
```
|
||||||
|
|
||||||
|
Archives a completed spec to declutter the Kanban board.
|
||||||
|
|
||||||
|
### Unarchive Spec
|
||||||
|
```http
|
||||||
|
POST /api/specs/{spec_id}/unarchive
|
||||||
|
```
|
||||||
|
|
||||||
|
Restores an archived spec.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Real-Time Spec Watcher (NEW)
|
||||||
|
|
||||||
|
Automatic file system monitoring for `agent-os/specs/` folders. Detects changes to spec files and auto-syncs to database for real-time Kanban updates.
|
||||||
|
|
||||||
|
**See:** `docs/guides/REALTIME_KANBAN_GUIDE.md` for complete documentation.
|
||||||
|
|
||||||
|
### Get Watcher Status
|
||||||
|
```http
|
||||||
|
GET /api/spec-watcher/status
|
||||||
|
```
|
||||||
|
|
||||||
|
**Response:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"status": {
|
||||||
|
"enabled": true,
|
||||||
|
"projects_watched": 1,
|
||||||
|
"projects": {
|
||||||
|
"1": {
|
||||||
|
"project_path": "/Users/you/Projects/myapp",
|
||||||
|
"specs_path": "/Users/you/Projects/myapp/agent-os/specs",
|
||||||
|
"watching": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Start Spec Watcher
|
||||||
|
```http
|
||||||
|
POST /api/spec-watcher/start/{project_id}
|
||||||
|
```
|
||||||
|
|
||||||
|
Starts real-time file watching for a specific project's specs folder.
|
||||||
|
|
||||||
|
**Response:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"project_id": 1,
|
||||||
|
"message": "Spec watcher started",
|
||||||
|
"status": {
|
||||||
|
"enabled": true,
|
||||||
|
"projects_watched": 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Stop Spec Watcher
|
||||||
|
```http
|
||||||
|
POST /api/spec-watcher/stop/{project_id}
|
||||||
|
```
|
||||||
|
|
||||||
|
Stops file watching for a specific project.
|
||||||
|
|
||||||
|
### Start All Spec Watchers
|
||||||
|
```http
|
||||||
|
POST /api/spec-watcher/start-all
|
||||||
|
```
|
||||||
|
|
||||||
|
Starts spec watchers for all projects in the database.
|
||||||
|
|
||||||
|
**Auto-Start:** Spec watchers automatically start when MCP server boots.
|
||||||
|
|
||||||
|
**How it works:**
|
||||||
|
1. Monitors `agent-os/specs/**/*.md` files
|
||||||
|
2. Detects changes with 2-second debounce
|
||||||
|
3. Auto-parses tasks in checkbox format
|
||||||
|
4. Updates database within 3 seconds
|
||||||
|
5. Kanban board auto-refreshes every 3 seconds
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## Hooks System
|
## Hooks System
|
||||||
|
|
||||||
### Enable Hook
|
### Enable Hook
|
||||||
|
|
|
||||||
452
docs/guides/REALTIME_KANBAN_GUIDE.md
Normal file
|
|
@ -0,0 +1,452 @@
|
||||||
|
# Real-Time Kanban Board Guide
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
Claude OS features a **real-time Kanban board** that automatically syncs with your agent-os spec files as they're created and updated. This provides live visibility into your development progress without any manual intervention.
|
||||||
|
|
||||||
|
## How It Works
|
||||||
|
|
||||||
|
The real-time Kanban system consists of three integrated components:
|
||||||
|
|
||||||
|
```
|
||||||
|
agent-os updates tasks.md
|
||||||
|
↓ (2 sec debounce)
|
||||||
|
Spec Watcher detects change
|
||||||
|
↓
|
||||||
|
Auto-syncs to database
|
||||||
|
↓ (within 3 seconds)
|
||||||
|
Kanban board auto-refreshes
|
||||||
|
↓
|
||||||
|
You see updated tasks in real-time! 🎉
|
||||||
|
```
|
||||||
|
|
||||||
|
### 1. Spec File Watcher
|
||||||
|
|
||||||
|
The **Spec Watcher** monitors your project's `agent-os/specs/` folder for file changes:
|
||||||
|
|
||||||
|
- **Watches**: All `tasks.md` and `spec.md` files in your specs folders
|
||||||
|
- **Triggers on**: File modifications and new file/folder creation
|
||||||
|
- **Debounce**: 2-second delay to batch rapid changes
|
||||||
|
- **Auto-starts**: Launches automatically when MCP server starts
|
||||||
|
|
||||||
|
**Technical Details:**
|
||||||
|
- Location: `app/core/spec_watcher.py`
|
||||||
|
- Uses: `watchdog` library for filesystem monitoring
|
||||||
|
- Monitors: `/path/to/project/agent-os/specs/**/*`
|
||||||
|
- Thread-safe: Uses locks for concurrent access
|
||||||
|
|
||||||
|
### 2. Automatic Database Sync
|
||||||
|
|
||||||
|
When the spec watcher detects changes, it:
|
||||||
|
|
||||||
|
1. Parses the updated `tasks.md` file
|
||||||
|
2. Extracts tasks in checkbox format:
|
||||||
|
```markdown
|
||||||
|
- [x] 1.0 Complete database layer
|
||||||
|
- [ ] 2.1 Write tests for services
|
||||||
|
```
|
||||||
|
3. Updates the SQLite database with new/modified tasks
|
||||||
|
4. Tracks task status (todo, in_progress, done, blocked)
|
||||||
|
|
||||||
|
**Supported Task Formats:**
|
||||||
|
|
||||||
|
The parser supports two formats:
|
||||||
|
|
||||||
|
**Checkbox Format** (recommended for agent-os):
|
||||||
|
```markdown
|
||||||
|
- [x] 1.0 Complete database layer
|
||||||
|
- [x] 1.1 Write 2-8 focused tests for database models
|
||||||
|
- [x] 1.2 Create migration: add_manual_time_slots_support
|
||||||
|
- [ ] 2.0 Complete service layer
|
||||||
|
- [ ] 2.1 Write 2-8 focused tests for services
|
||||||
|
```
|
||||||
|
|
||||||
|
**Classic Format** (legacy support):
|
||||||
|
```markdown
|
||||||
|
### PHASE1-TASK1: Database Setup
|
||||||
|
**Title:** Setup Database Schema
|
||||||
|
**Description:** Create all required database tables
|
||||||
|
**Estimated Time:** 2 hours
|
||||||
|
**Risk Level:** low
|
||||||
|
**Status:** ✅ COMPLETED
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. Frontend Auto-Refresh
|
||||||
|
|
||||||
|
The Kanban board frontend:
|
||||||
|
|
||||||
|
- **Polls**: Every 3 seconds for database updates
|
||||||
|
- **Refreshes**: Automatically when new data is detected
|
||||||
|
- **Smooth**: Uses React Query for optimistic updates
|
||||||
|
- **Animations**: Framer Motion for smooth task transitions
|
||||||
|
|
||||||
|
## Using the Kanban Board
|
||||||
|
|
||||||
|
### Accessing the Board
|
||||||
|
|
||||||
|
1. Open Claude OS web interface
|
||||||
|
2. Select your project from the sidebar
|
||||||
|
3. Click the **"Kanban Board"** tab
|
||||||
|
4. Board loads automatically with all specs and tasks
|
||||||
|
|
||||||
|
### Board Layout
|
||||||
|
|
||||||
|
The Kanban board displays:
|
||||||
|
|
||||||
|
**Top Section:**
|
||||||
|
- Summary statistics (total specs, total tasks, completed tasks)
|
||||||
|
- "Sync Specs" button (manual sync if needed)
|
||||||
|
- "Show Archived" toggle
|
||||||
|
|
||||||
|
**Spec Cards:**
|
||||||
|
Each spec shows:
|
||||||
|
- Spec name and status
|
||||||
|
- Progress bar
|
||||||
|
- Task counts by status
|
||||||
|
- Four columns: Todo, In Progress, Done, Blocked
|
||||||
|
|
||||||
|
**Task Cards:**
|
||||||
|
- Task code (e.g., PHASE1-TASK1)
|
||||||
|
- Title
|
||||||
|
- Risk level badge
|
||||||
|
- Estimated/actual time
|
||||||
|
- Dependencies
|
||||||
|
|
||||||
|
### Manual Sync Button
|
||||||
|
|
||||||
|
While the board updates automatically, you can manually trigger a sync:
|
||||||
|
|
||||||
|
1. Click **"Sync Specs"** button at the top
|
||||||
|
2. All spec files are re-parsed
|
||||||
|
3. Database updates immediately
|
||||||
|
4. Board refreshes within 3 seconds
|
||||||
|
|
||||||
|
Use this when:
|
||||||
|
- Testing the sync functionality
|
||||||
|
- Recovering from errors
|
||||||
|
- Adding a new spec folder manually
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
### Spec Watcher Management
|
||||||
|
|
||||||
|
The spec watcher starts automatically, but you can control it via API:
|
||||||
|
|
||||||
|
**Start watcher for a project:**
|
||||||
|
```bash
|
||||||
|
curl -X POST http://localhost:8051/api/spec-watcher/start/{project_id}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Stop watcher for a project:**
|
||||||
|
```bash
|
||||||
|
curl -X POST http://localhost:8051/api/spec-watcher/stop/{project_id}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Start all project watchers:**
|
||||||
|
```bash
|
||||||
|
curl -X POST http://localhost:8051/api/spec-watcher/start-all
|
||||||
|
```
|
||||||
|
|
||||||
|
**Check watcher status:**
|
||||||
|
```bash
|
||||||
|
curl http://localhost:8051/api/spec-watcher/status
|
||||||
|
```
|
||||||
|
|
||||||
|
Example status response:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"status": {
|
||||||
|
"enabled": true,
|
||||||
|
"projects_watched": 1,
|
||||||
|
"projects": {
|
||||||
|
"1": {
|
||||||
|
"project_path": "/Users/you/Projects/myapp",
|
||||||
|
"specs_path": "/Users/you/Projects/myapp/agent-os/specs",
|
||||||
|
"watching": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Adjusting Refresh Rate
|
||||||
|
|
||||||
|
The default refresh rate is 3 seconds. To change it:
|
||||||
|
|
||||||
|
**File:** `frontend/src/components/KanbanBoard.tsx`
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const { data: kanbanData, isLoading } = useQuery({
|
||||||
|
queryKey: ['kanban', projectId, includeArchived],
|
||||||
|
queryFn: async () => {
|
||||||
|
// ... fetch logic
|
||||||
|
},
|
||||||
|
refetchInterval: 3000, // Change this value (milliseconds)
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
**Recommended values:**
|
||||||
|
- **3000ms (3s)**: Real-time updates, good UX
|
||||||
|
- **5000ms (5s)**: Balanced performance
|
||||||
|
- **10000ms (10s)**: Low-traffic, battery-saving
|
||||||
|
|
||||||
|
### Debounce Delay
|
||||||
|
|
||||||
|
The spec watcher waits 2 seconds after detecting a change before syncing. To adjust:
|
||||||
|
|
||||||
|
**File:** `app/core/spec_watcher.py`
|
||||||
|
|
||||||
|
```python
|
||||||
|
class SpecFileHandler(FileSystemEventHandler):
|
||||||
|
def __init__(self, project_id: int, project_path: str):
|
||||||
|
# ...
|
||||||
|
self.debounce_delay = 2.0 # Change this value (seconds)
|
||||||
|
```
|
||||||
|
|
||||||
|
**Why debounce?**
|
||||||
|
- Prevents sync spam during rapid file edits
|
||||||
|
- Batches related changes together
|
||||||
|
- Reduces database load
|
||||||
|
|
||||||
|
## Project Structure Requirements
|
||||||
|
|
||||||
|
For the Kanban board to work, your project must have this structure:
|
||||||
|
|
||||||
|
```
|
||||||
|
your-project/
|
||||||
|
└── agent-os/
|
||||||
|
└── specs/
|
||||||
|
├── 2025-10-29-feature-name/
|
||||||
|
│ ├── spec.md # Optional: Feature specification
|
||||||
|
│ └── tasks.md # Required: Task breakdown
|
||||||
|
└── 2025-11-01-another-feature/
|
||||||
|
├── spec.md
|
||||||
|
└── tasks.md
|
||||||
|
```
|
||||||
|
|
||||||
|
**Folder naming convention:**
|
||||||
|
- Format: `YYYY-MM-DD-feature-slug`
|
||||||
|
- Example: `2025-10-29-manual-appointment-times`
|
||||||
|
- Slug becomes the spec name (spaces replace hyphens)
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
### Tasks Not Showing Up
|
||||||
|
|
||||||
|
**Check 1: Is the spec watcher running?**
|
||||||
|
```bash
|
||||||
|
curl http://localhost:8051/api/spec-watcher/status
|
||||||
|
```
|
||||||
|
|
||||||
|
If `"watching": false`, restart the watcher:
|
||||||
|
```bash
|
||||||
|
curl -X POST http://localhost:8051/api/spec-watcher/start/{project_id}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Check 2: Are your tasks in the right format?**
|
||||||
|
|
||||||
|
Tasks must use the checkbox format with numeric prefixes:
|
||||||
|
```markdown
|
||||||
|
- [ ] 1.0 Task title
|
||||||
|
- [x] 2.1 Another task
|
||||||
|
```
|
||||||
|
|
||||||
|
Not this:
|
||||||
|
```markdown
|
||||||
|
- [ ] Task without number
|
||||||
|
- Some random text
|
||||||
|
```
|
||||||
|
|
||||||
|
**Check 3: Is tasks.md in the right location?**
|
||||||
|
```
|
||||||
|
✅ project/agent-os/specs/2025-10-29-feature/tasks.md
|
||||||
|
❌ project/specs/tasks.md
|
||||||
|
❌ project/agent-os/tasks.md
|
||||||
|
```
|
||||||
|
|
||||||
|
**Check 4: Check the MCP server logs**
|
||||||
|
```bash
|
||||||
|
tail -50 logs/mcp_server.log
|
||||||
|
```
|
||||||
|
|
||||||
|
Look for:
|
||||||
|
- `✅ Updated spec 'Feature Name' with X tasks`
|
||||||
|
- Any error messages about parsing
|
||||||
|
|
||||||
|
### Board Not Auto-Refreshing
|
||||||
|
|
||||||
|
**Check 1: Is polling enabled?**
|
||||||
|
|
||||||
|
Open browser DevTools → Network tab → Filter by "kanban"
|
||||||
|
|
||||||
|
You should see requests every 3 seconds to:
|
||||||
|
```
|
||||||
|
GET /api/projects/1/kanban?include_archived=false
|
||||||
|
```
|
||||||
|
|
||||||
|
If not, check that React Query is configured correctly.
|
||||||
|
|
||||||
|
**Check 2: Clear browser cache**
|
||||||
|
```
|
||||||
|
Ctrl+Shift+R (Windows/Linux)
|
||||||
|
Cmd+Shift+R (Mac)
|
||||||
|
```
|
||||||
|
|
||||||
|
**Check 3: Check frontend logs**
|
||||||
|
|
||||||
|
Open browser Console and look for errors related to:
|
||||||
|
- React Query
|
||||||
|
- Axios requests
|
||||||
|
- WebSocket connections (if applicable)
|
||||||
|
|
||||||
|
### Sync Taking Too Long
|
||||||
|
|
||||||
|
**Expected timings:**
|
||||||
|
- File change detected: < 1 second
|
||||||
|
- Debounce wait: 2 seconds
|
||||||
|
- Database sync: < 1 second
|
||||||
|
- Frontend refresh: 3 seconds
|
||||||
|
- **Total**: ~6 seconds max
|
||||||
|
|
||||||
|
**If slower:**
|
||||||
|
|
||||||
|
1. Check disk I/O (is your disk slow?)
|
||||||
|
2. Check database size (vacuum if needed):
|
||||||
|
```bash
|
||||||
|
sqlite3 data/claude-os.db "VACUUM;"
|
||||||
|
```
|
||||||
|
3. Check CPU usage (spec parsing is CPU-intensive for large specs)
|
||||||
|
|
||||||
|
### Parser Errors
|
||||||
|
|
||||||
|
**Common issues:**
|
||||||
|
|
||||||
|
**Issue:** "No tasks found"
|
||||||
|
- **Cause:** Tasks not in checkbox format
|
||||||
|
- **Fix:** Add `- [ ]` or `- [x]` before task lines
|
||||||
|
|
||||||
|
**Issue:** "Invalid task code"
|
||||||
|
- **Cause:** Missing numeric prefix (e.g., `1.0`, `2.1`)
|
||||||
|
- **Fix:** Add numbers: `- [ ] 1.0 Task title`
|
||||||
|
|
||||||
|
**Issue:** "Spec not found"
|
||||||
|
- **Cause:** Folder name doesn't match expected format
|
||||||
|
- **Fix:** Rename to `YYYY-MM-DD-feature-name`
|
||||||
|
|
||||||
|
## Advanced Usage
|
||||||
|
|
||||||
|
### Custom Task Status Updates
|
||||||
|
|
||||||
|
You can manually update task status via API:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl -X PATCH http://localhost:8051/api/tasks/{task_id}/status \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d '{
|
||||||
|
"status": "in_progress",
|
||||||
|
"actual_minutes": 120
|
||||||
|
}'
|
||||||
|
```
|
||||||
|
|
||||||
|
Valid statuses: `todo`, `in_progress`, `done`, `blocked`
|
||||||
|
|
||||||
|
### Archiving Specs
|
||||||
|
|
||||||
|
Archive completed specs to declutter the board:
|
||||||
|
|
||||||
|
**Via UI:**
|
||||||
|
1. Click "Archive" button on spec card
|
||||||
|
2. Spec moves to archived view
|
||||||
|
|
||||||
|
**Via API:**
|
||||||
|
```bash
|
||||||
|
curl -X POST http://localhost:8051/api/specs/{spec_id}/archive
|
||||||
|
```
|
||||||
|
|
||||||
|
**To view archived specs:**
|
||||||
|
- Toggle "Show Archived" checkbox in the UI
|
||||||
|
|
||||||
|
### Bulk Operations
|
||||||
|
|
||||||
|
**Sync all specs for a project:**
|
||||||
|
```bash
|
||||||
|
curl -X POST http://localhost:8051/api/projects/{project_id}/specs/sync
|
||||||
|
```
|
||||||
|
|
||||||
|
Response:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"project_id": 1,
|
||||||
|
"message": "Specs synced successfully",
|
||||||
|
"synced": 0,
|
||||||
|
"updated": 3,
|
||||||
|
"total": 3,
|
||||||
|
"errors": []
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Performance Considerations
|
||||||
|
|
||||||
|
### Database Size
|
||||||
|
|
||||||
|
Each task creates a database row. For large projects:
|
||||||
|
|
||||||
|
**Estimate storage:**
|
||||||
|
- 100 specs × 50 tasks = 5,000 rows
|
||||||
|
- SQLite handles this easily (millions of rows supported)
|
||||||
|
|
||||||
|
**Optimize periodically:**
|
||||||
|
```bash
|
||||||
|
sqlite3 data/claude-os.db "VACUUM; ANALYZE;"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Frontend Performance
|
||||||
|
|
||||||
|
With many tasks, the Kanban board may slow down:
|
||||||
|
|
||||||
|
**Optimization tips:**
|
||||||
|
1. Archive old specs (reduces rendered tasks)
|
||||||
|
2. Increase refresh interval to 5-10 seconds
|
||||||
|
3. Filter by status (show only active tasks)
|
||||||
|
|
||||||
|
### File Watcher Overhead
|
||||||
|
|
||||||
|
The spec watcher uses minimal resources:
|
||||||
|
- CPU: < 1% idle, ~5% during sync
|
||||||
|
- Memory: ~20 MB per project
|
||||||
|
- Disk I/O: Only on file changes
|
||||||
|
|
||||||
|
**Disable if needed:**
|
||||||
|
```bash
|
||||||
|
curl -X POST http://localhost:8051/api/spec-watcher/stop/{project_id}
|
||||||
|
```
|
||||||
|
|
||||||
|
## API Reference
|
||||||
|
|
||||||
|
See full API documentation in `docs/API_REFERENCE.md`
|
||||||
|
|
||||||
|
**Key endpoints:**
|
||||||
|
|
||||||
|
- `GET /api/projects/{id}/kanban` - Get Kanban data
|
||||||
|
- `GET /api/projects/{id}/specs` - List all specs
|
||||||
|
- `POST /api/projects/{id}/specs/sync` - Manual sync
|
||||||
|
- `PATCH /api/tasks/{id}/status` - Update task status
|
||||||
|
- `POST /api/specs/{id}/archive` - Archive spec
|
||||||
|
- `GET /api/spec-watcher/status` - Watcher status
|
||||||
|
|
||||||
|
## Related Documentation
|
||||||
|
|
||||||
|
- **What is Claude OS**: `docs/guides/WHAT_IS_CLAUDE_OS.md`
|
||||||
|
- **Session Workflow**: `docs/guides/IDEAL_SESSION_WORKFLOW.md`
|
||||||
|
- **API Reference**: `docs/API_REFERENCE.md`
|
||||||
|
- **Quick Start**: `docs/QUICK_START_CLAUDE_OS.md`
|
||||||
|
|
||||||
|
## Support
|
||||||
|
|
||||||
|
If you encounter issues:
|
||||||
|
|
||||||
|
1. Check the logs: `tail -f logs/mcp_server.log`
|
||||||
|
2. Check watcher status: `curl http://localhost:8051/api/spec-watcher/status`
|
||||||
|
3. Try manual sync: Click "Sync Specs" button
|
||||||
|
4. Restart MCP server: `./scripts/restart_mcp.sh`
|
||||||
|
5. Open an issue: [GitHub Issues](https://github.com/anthropics/claude-os/issues)
|
||||||
451
docs/guides/VISUAL_GUIDE.md
Normal file
|
|
@ -0,0 +1,451 @@
|
||||||
|
# Claude OS Visual Guide
|
||||||
|
|
||||||
|
**A complete visual tour of the Claude OS interface**
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📸 Full Application Tour
|
||||||
|
|
||||||
|
### 1. Welcome Screen
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
**What you see:**
|
||||||
|
- Claude OS hero image and branding
|
||||||
|
- Quick start guide
|
||||||
|
- Links to documentation
|
||||||
|
- Get started button
|
||||||
|
|
||||||
|
**What you can do:**
|
||||||
|
- Learn about Claude OS features
|
||||||
|
- Access documentation
|
||||||
|
- Navigate to the main application
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 2. Projects List
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
**What you see:**
|
||||||
|
- All your Claude OS projects
|
||||||
|
- Project names and paths
|
||||||
|
- Quick actions (delete, configure)
|
||||||
|
- Create new project button
|
||||||
|
|
||||||
|
**What you can do:**
|
||||||
|
- View all projects
|
||||||
|
- Select a project to work with
|
||||||
|
- Create new projects
|
||||||
|
- Delete old projects
|
||||||
|
- See project metadata
|
||||||
|
|
||||||
|
**Key Features:**
|
||||||
|
- ✅ Fast project switching
|
||||||
|
- ✅ Visual project cards
|
||||||
|
- ✅ Quick project creation
|
||||||
|
- ✅ Project organization
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 3. Project Overview
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
**What you see:**
|
||||||
|
- Project name and description
|
||||||
|
- Database ID
|
||||||
|
- Project path
|
||||||
|
- MCP configuration status (X of 5 MCPs)
|
||||||
|
- List of configured MCPs:
|
||||||
|
- knowledge_docs
|
||||||
|
- project_profile
|
||||||
|
- project_index
|
||||||
|
- project_memories
|
||||||
|
- code_structure
|
||||||
|
|
||||||
|
**What you can do:**
|
||||||
|
- View project details
|
||||||
|
- Check MCP configuration
|
||||||
|
- Access configure button
|
||||||
|
- See which MCPs are set up
|
||||||
|
- Understand project structure
|
||||||
|
|
||||||
|
**Key Features:**
|
||||||
|
- ✅ Complete project metadata
|
||||||
|
- ✅ MCP status at a glance
|
||||||
|
- ✅ Configuration access
|
||||||
|
- ✅ Visual MCP indicators (configured vs not configured)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 4. Kanban Board
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
**What you see:**
|
||||||
|
- Project specs organized as Kanban boards
|
||||||
|
- Progress bars for each spec
|
||||||
|
- Task counts by status (Todo/In Progress/Done/Blocked)
|
||||||
|
- Sync specs button
|
||||||
|
- Show archived toggle
|
||||||
|
- Summary statistics:
|
||||||
|
- Total specs
|
||||||
|
- Total tasks
|
||||||
|
- Completion percentage
|
||||||
|
|
||||||
|
**What you can do:**
|
||||||
|
- View all active specs
|
||||||
|
- See task progress visually
|
||||||
|
- Click tasks to view details
|
||||||
|
- Update task status
|
||||||
|
- Archive completed specs
|
||||||
|
- Sync new specs from agent-os folder
|
||||||
|
- Track implementation progress
|
||||||
|
|
||||||
|
**Key Features:**
|
||||||
|
- ✅ Visual progress tracking
|
||||||
|
- ✅ Real-time task management
|
||||||
|
- ✅ Archive completed work
|
||||||
|
- ✅ Automatic sync from agent-os
|
||||||
|
- ✅ Progress percentages
|
||||||
|
- ✅ Task organization by phase
|
||||||
|
|
||||||
|
**Perfect for:**
|
||||||
|
- Tracking Agent-OS spec implementation
|
||||||
|
- Visualizing project progress
|
||||||
|
- Managing task workflow
|
||||||
|
- Team collaboration
|
||||||
|
- Sprint planning
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 4.5. Task Detail Modal
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
**What you see:**
|
||||||
|
- Task code and title
|
||||||
|
- Full task description
|
||||||
|
- Current status
|
||||||
|
- Time estimates (estimated vs actual)
|
||||||
|
- Risk level
|
||||||
|
- Dependencies
|
||||||
|
- Status update buttons
|
||||||
|
|
||||||
|
**What you can do:**
|
||||||
|
- View complete task details
|
||||||
|
- Update task status (Todo → In Progress → Done → Blocked)
|
||||||
|
- Track time spent vs estimated
|
||||||
|
- See task dependencies
|
||||||
|
- Close modal to return to Kanban board
|
||||||
|
|
||||||
|
**Key Features:**
|
||||||
|
- ✅ Quick status updates
|
||||||
|
- ✅ Time tracking
|
||||||
|
- ✅ Risk visibility
|
||||||
|
- ✅ Dependency awareness
|
||||||
|
- ✅ Clean modal interface
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 6. MCP Management
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
**What you see:**
|
||||||
|
- Selected MCP knowledge base
|
||||||
|
- Document list
|
||||||
|
- Upload interface
|
||||||
|
- Search functionality
|
||||||
|
- KB statistics
|
||||||
|
|
||||||
|
**What you can do:**
|
||||||
|
- Browse documents in knowledge base
|
||||||
|
- Upload new documents (.md, .txt, .pdf, code files)
|
||||||
|
- Search across KB
|
||||||
|
- View KB stats
|
||||||
|
- Manage knowledge base content
|
||||||
|
|
||||||
|
**Key Features:**
|
||||||
|
- ✅ Drag & drop file upload
|
||||||
|
- ✅ Multi-file support
|
||||||
|
- ✅ Document browser
|
||||||
|
- ✅ Search within KB
|
||||||
|
- ✅ File type indicators
|
||||||
|
|
||||||
|
**Supported Knowledge Bases:**
|
||||||
|
- **project_memories** - Your decisions and insights
|
||||||
|
- **project_profile** - Coding standards and architecture
|
||||||
|
- **project_index** - Automated codebase index
|
||||||
|
- **knowledge_docs** - Documentation and guides
|
||||||
|
- **code_structure** - Tree-sitter structural index
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 7. Chat Interface
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
**What you see:**
|
||||||
|
- Chat conversation with Claude
|
||||||
|
- Message history
|
||||||
|
- Input field
|
||||||
|
- RAG settings:
|
||||||
|
- Hybrid Search toggle
|
||||||
|
- Reranking toggle
|
||||||
|
- Agentic RAG toggle
|
||||||
|
|
||||||
|
**What you can do:**
|
||||||
|
- Ask questions about your project
|
||||||
|
- Search knowledge bases conversationally
|
||||||
|
- Get AI-powered answers with citations
|
||||||
|
- Adjust search strategies
|
||||||
|
- Reference past conversations
|
||||||
|
|
||||||
|
**Key Features:**
|
||||||
|
- ✅ Natural language queries
|
||||||
|
- ✅ Semantic search across KBs
|
||||||
|
- ✅ Source citations
|
||||||
|
- ✅ Customizable RAG strategies
|
||||||
|
- ✅ Context-aware responses
|
||||||
|
|
||||||
|
**RAG Settings:**
|
||||||
|
- **Hybrid Search** - Combines semantic + keyword search
|
||||||
|
- **Reranking** - Re-orders results for better relevance
|
||||||
|
- **Agentic RAG** - AI-powered query refinement
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 8. Services Dashboard
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
**What you see:**
|
||||||
|
- All Claude OS services status
|
||||||
|
- Service health indicators (Running/Stopped)
|
||||||
|
- Individual service cards:
|
||||||
|
- MCP Server (port 8051)
|
||||||
|
- Frontend Server (port 5173)
|
||||||
|
- RQ Worker
|
||||||
|
- File Watcher
|
||||||
|
- Redis
|
||||||
|
- Ollama
|
||||||
|
|
||||||
|
**What you can do:**
|
||||||
|
- Monitor service health
|
||||||
|
- See which services are running
|
||||||
|
- Check service ports
|
||||||
|
- Identify issues quickly
|
||||||
|
- Verify complete stack status
|
||||||
|
|
||||||
|
**Key Features:**
|
||||||
|
- ✅ Real-time service monitoring
|
||||||
|
- ✅ Visual status indicators
|
||||||
|
- ✅ Port information
|
||||||
|
- ✅ Service descriptions
|
||||||
|
- ✅ Quick health check
|
||||||
|
|
||||||
|
**Service Details:**
|
||||||
|
|
||||||
|
| Service | Purpose | Port |
|
||||||
|
|---------|---------|------|
|
||||||
|
| **MCP Server** | FastAPI backend, knowledge base APIs | 8051 |
|
||||||
|
| **Frontend** | React UI (Vite dev server) | 5173 |
|
||||||
|
| **RQ Worker** | Background job processing | - |
|
||||||
|
| **File Watcher** | Auto-sync knowledge_docs folders | - |
|
||||||
|
| **Redis** | Cache & job queue | 6379 |
|
||||||
|
| **Ollama** | Local LLM inference | 11434 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 9. Mobile Experience
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
**What you see:**
|
||||||
|
- Responsive mobile interface
|
||||||
|
- Optimized navigation
|
||||||
|
- Touch-friendly controls
|
||||||
|
- Mobile-optimized layouts
|
||||||
|
|
||||||
|
**What you can do:**
|
||||||
|
- Access Claude OS from any device
|
||||||
|
- Use all features on mobile
|
||||||
|
- Responsive design adapts to screen size
|
||||||
|
- Full functionality on tablets and phones
|
||||||
|
|
||||||
|
**Key Features:**
|
||||||
|
- ✅ Fully responsive design
|
||||||
|
- ✅ Touch-optimized UI
|
||||||
|
- ✅ Mobile navigation
|
||||||
|
- ✅ All features accessible on mobile
|
||||||
|
- ✅ Supports all modern mobile browsers
|
||||||
|
|
||||||
|
**Supported Devices:**
|
||||||
|
- 📱 iPhone (iOS 14+)
|
||||||
|
- 📱 Android phones
|
||||||
|
- 📱 Tablets (iPad, Android)
|
||||||
|
- 💻 Any screen size from 375px to 1920px+
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🎯 Navigation Flow
|
||||||
|
|
||||||
|
### Typical Workflow
|
||||||
|
|
||||||
|
```
|
||||||
|
1. Welcome Screen
|
||||||
|
↓
|
||||||
|
2. Projects List → Select/Create Project
|
||||||
|
↓
|
||||||
|
3. Project Overview → See MCP Status
|
||||||
|
↓
|
||||||
|
4. Choose a Tab:
|
||||||
|
├─→ Kanban Board (track implementation)
|
||||||
|
├─→ MCP Management (upload docs)
|
||||||
|
├─→ Chat (ask questions)
|
||||||
|
└─→ Services (monitor health)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Quick Access Paths
|
||||||
|
|
||||||
|
**To track spec progress:**
|
||||||
|
```
|
||||||
|
Projects List → Select Project → Kanban Board Tab
|
||||||
|
```
|
||||||
|
|
||||||
|
**To upload documentation:**
|
||||||
|
```
|
||||||
|
Projects List → Select Project → MCP Management → Select KB → Upload
|
||||||
|
```
|
||||||
|
|
||||||
|
**To ask project questions:**
|
||||||
|
```
|
||||||
|
Projects List → Select Project → Chat Tab
|
||||||
|
```
|
||||||
|
|
||||||
|
**To check service health:**
|
||||||
|
```
|
||||||
|
Projects List → Select Project → Services Tab
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🎨 UI Components
|
||||||
|
|
||||||
|
### Common Elements
|
||||||
|
|
||||||
|
**Sidebar (Left):**
|
||||||
|
- Projects list
|
||||||
|
- Project MCPs
|
||||||
|
- RAG settings
|
||||||
|
- Quick actions
|
||||||
|
|
||||||
|
**Top Navigation:**
|
||||||
|
- Home button
|
||||||
|
- Project name
|
||||||
|
- Tab navigation
|
||||||
|
- Welcome link
|
||||||
|
|
||||||
|
**Main Content:**
|
||||||
|
- Tab-specific content
|
||||||
|
- Interactive elements
|
||||||
|
- Real-time data
|
||||||
|
|
||||||
|
**Status Indicators:**
|
||||||
|
- ✅ Green = Success/Active
|
||||||
|
- ⏸️ Yellow = Paused
|
||||||
|
- ❌ Red = Error/Stopped
|
||||||
|
- 📊 Blue = In Progress
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📱 Responsive Design
|
||||||
|
|
||||||
|
All pages are designed to work on:
|
||||||
|
- 💻 Desktop (1920px+)
|
||||||
|
- 💻 Laptop (1440px)
|
||||||
|
- 📱 Tablet (768px)
|
||||||
|
- 📱 Mobile (375px+)
|
||||||
|
|
||||||
|
**Optimized for:**
|
||||||
|
- Chrome
|
||||||
|
- Firefox
|
||||||
|
- Safari
|
||||||
|
- Edge
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🎯 Feature Highlights by Page
|
||||||
|
|
||||||
|
### Welcome Screen
|
||||||
|
- First-time user onboarding
|
||||||
|
- Feature introduction
|
||||||
|
- Documentation access
|
||||||
|
|
||||||
|
### Projects List
|
||||||
|
- Multi-project management
|
||||||
|
- Quick project switching
|
||||||
|
- Project creation wizard
|
||||||
|
|
||||||
|
### Project Overview
|
||||||
|
- At-a-glance project status
|
||||||
|
- MCP configuration visibility
|
||||||
|
- Quick configuration access
|
||||||
|
|
||||||
|
### Kanban Board
|
||||||
|
- Visual task management
|
||||||
|
- Progress tracking
|
||||||
|
- Spec implementation workflow
|
||||||
|
- Archive management
|
||||||
|
|
||||||
|
### MCP Management
|
||||||
|
- Knowledge base content management
|
||||||
|
- Document upload
|
||||||
|
- KB organization
|
||||||
|
|
||||||
|
### Chat Interface
|
||||||
|
- Natural language queries
|
||||||
|
- Semantic search
|
||||||
|
- AI-powered answers
|
||||||
|
|
||||||
|
### Services Dashboard
|
||||||
|
- System health monitoring
|
||||||
|
- Service status visibility
|
||||||
|
- Quick diagnostics
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🚀 Getting Started
|
||||||
|
|
||||||
|
**For new users:**
|
||||||
|
|
||||||
|
1. Start at **Welcome Screen** → Learn about features
|
||||||
|
2. Go to **Projects List** → Create your first project
|
||||||
|
3. View **Project Overview** → See MCP setup
|
||||||
|
4. Visit **MCP Management** → Upload documentation
|
||||||
|
5. Try **Chat** → Ask questions about your docs
|
||||||
|
6. Check **Kanban** → Track spec implementation
|
||||||
|
7. Monitor **Services** → Ensure everything running
|
||||||
|
|
||||||
|
**For experienced users:**
|
||||||
|
|
||||||
|
1. **Projects List** → Select project
|
||||||
|
2. **Kanban** → Continue implementation
|
||||||
|
3. **Chat** → Quick questions as needed
|
||||||
|
4. **Services** → Occasional health check
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📖 Related Documentation
|
||||||
|
|
||||||
|
- **[README.md](../../README.md)** - Complete setup guide
|
||||||
|
- **[WHAT_IS_CLAUDE_OS.md](./WHAT_IS_CLAUDE_OS.md)** - Feature overview
|
||||||
|
- **[KANBAN_BOARD_GUIDE.md](./KANBAN_BOARD_GUIDE.md)** - Kanban detailed guide
|
||||||
|
- **[SESSION_START_PROTOCOL.md](./SESSION_START_PROTOCOL.md)** - Session management
|
||||||
|
- **[API_REFERENCE.md](../API_REFERENCE.md)** - Complete API docs
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**This visual guide shows the complete Claude OS interface. Every screenshot is from the actual application running with real project data!** 🎉
|
||||||
64
frontend/package-lock.json
generated
|
|
@ -21,6 +21,7 @@
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@eslint/js": "^9.36.0",
|
"@eslint/js": "^9.36.0",
|
||||||
|
"@playwright/test": "^1.56.1",
|
||||||
"@tailwindcss/typography": "^0.5.19",
|
"@tailwindcss/typography": "^0.5.19",
|
||||||
"@types/node": "^24.6.0",
|
"@types/node": "^24.6.0",
|
||||||
"@types/react": "^19.1.16",
|
"@types/react": "^19.1.16",
|
||||||
|
|
@ -1111,6 +1112,22 @@
|
||||||
"node": ">=14"
|
"node": ">=14"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@playwright/test": {
|
||||||
|
"version": "1.56.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.56.1.tgz",
|
||||||
|
"integrity": "sha512-vSMYtL/zOcFpvJCW71Q/OEGQb7KYBPAdKh35WNSkaZA75JlAO8ED8UN6GUNTm3drWomcbcqRPFqQbLae8yBTdg==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"dependencies": {
|
||||||
|
"playwright": "1.56.1"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"playwright": "cli.js"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@rolldown/pluginutils": {
|
"node_modules/@rolldown/pluginutils": {
|
||||||
"version": "1.0.0-beta.38",
|
"version": "1.0.0-beta.38",
|
||||||
"resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.38.tgz",
|
"resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.38.tgz",
|
||||||
|
|
@ -4771,6 +4788,53 @@
|
||||||
"node": ">= 6"
|
"node": ">= 6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/playwright": {
|
||||||
|
"version": "1.56.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/playwright/-/playwright-1.56.1.tgz",
|
||||||
|
"integrity": "sha512-aFi5B0WovBHTEvpM3DzXTUaeN6eN0qWnTkKx4NQaH4Wvcmc153PdaY2UBdSYKaGYw+UyWXSVyxDUg5DoPEttjw==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"dependencies": {
|
||||||
|
"playwright-core": "1.56.1"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"playwright": "cli.js"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18"
|
||||||
|
},
|
||||||
|
"optionalDependencies": {
|
||||||
|
"fsevents": "2.3.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/playwright-core": {
|
||||||
|
"version": "1.56.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.56.1.tgz",
|
||||||
|
"integrity": "sha512-hutraynyn31F+Bifme+Ps9Vq59hKuUCz7H1kDOcBs+2oGguKkWTU50bBWrtz34OUWmIwpBTWDxaRPXrIXkgvmQ==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"bin": {
|
||||||
|
"playwright-core": "cli.js"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/playwright/node_modules/fsevents": {
|
||||||
|
"version": "2.3.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
|
||||||
|
"integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
|
||||||
|
"dev": true,
|
||||||
|
"hasInstallScript": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"darwin"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": "^8.16.0 || ^10.6.0 || >=11.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/postcss": {
|
"node_modules/postcss": {
|
||||||
"version": "8.5.6",
|
"version": "8.5.6",
|
||||||
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz",
|
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz",
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,8 @@
|
||||||
"dev": "vite",
|
"dev": "vite",
|
||||||
"build": "tsc -b && vite build",
|
"build": "tsc -b && vite build",
|
||||||
"lint": "eslint .",
|
"lint": "eslint .",
|
||||||
"preview": "vite preview"
|
"preview": "vite preview",
|
||||||
|
"screenshots": "node ../scripts/capture-screenshots.js"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@tanstack/react-query": "^5.90.5",
|
"@tanstack/react-query": "^5.90.5",
|
||||||
|
|
@ -23,6 +24,7 @@
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@eslint/js": "^9.36.0",
|
"@eslint/js": "^9.36.0",
|
||||||
|
"@playwright/test": "^1.56.1",
|
||||||
"@tailwindcss/typography": "^0.5.19",
|
"@tailwindcss/typography": "^0.5.19",
|
||||||
"@types/node": "^24.6.0",
|
"@types/node": "^24.6.0",
|
||||||
"@types/react": "^19.1.16",
|
"@types/react": "^19.1.16",
|
||||||
|
|
|
||||||
BIN
frontend/public/assets/screenshots/kanban-task-detail-modal.png
Normal file
|
After Width: | Height: | Size: 188 KiB |
BIN
frontend/public/assets/screenshots/mobile-welcome-screen.png
Normal file
|
After Width: | Height: | Size: 122 KiB |
BIN
frontend/public/assets/screenshots/project-chat-page.png
Normal file
|
After Width: | Height: | Size: 116 KiB |
BIN
frontend/public/assets/screenshots/project-kanban-page.png
Normal file
|
After Width: | Height: | Size: 894 KiB |
BIN
frontend/public/assets/screenshots/project-mcp-page.png
Normal file
|
After Width: | Height: | Size: 188 KiB |
BIN
frontend/public/assets/screenshots/project-overview-page.png
Normal file
|
After Width: | Height: | Size: 132 KiB |
|
After Width: | Height: | Size: 202 KiB |
BIN
frontend/public/assets/screenshots/projects-list-page.png
Normal file
|
After Width: | Height: | Size: 65 KiB |
BIN
frontend/public/assets/screenshots/welcome-screen.png
Normal file
|
After Width: | Height: | Size: 356 KiB |
|
|
@ -69,7 +69,7 @@ export default function KanbanBoard({ projectId }: KanbanBoardProps) {
|
||||||
});
|
});
|
||||||
return response.data;
|
return response.data;
|
||||||
},
|
},
|
||||||
refetchInterval: 30000, // Refetch every 30 seconds
|
refetchInterval: 3000, // Refetch every 3 seconds for real-time updates
|
||||||
});
|
});
|
||||||
|
|
||||||
// Sync specs mutation
|
// Sync specs mutation
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,12 @@ import react from '@vitejs/plugin-react'
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
plugins: [react()],
|
plugins: [react()],
|
||||||
server: {
|
server: {
|
||||||
|
host: true,
|
||||||
|
allowedHosts: [
|
||||||
|
'localhost',
|
||||||
|
'.ngrok-free.app',
|
||||||
|
'daa65fe0204a.ngrok-free.app'
|
||||||
|
],
|
||||||
proxy: {
|
proxy: {
|
||||||
'/api': {
|
'/api': {
|
||||||
target: 'http://localhost:8051',
|
target: 'http://localhost:8051',
|
||||||
|
|
|
||||||
|
|
@ -1591,6 +1591,85 @@ async def api_watcher_status():
|
||||||
raise HTTPException(status_code=500, detail=str(e))
|
raise HTTPException(status_code=500, detail=str(e))
|
||||||
|
|
||||||
|
|
||||||
|
# ============================================================================
|
||||||
|
# SPEC WATCHER ENDPOINTS (for real-time agent-os spec syncing)
|
||||||
|
# ============================================================================
|
||||||
|
|
||||||
|
@app.post("/api/spec-watcher/start/{project_id}")
|
||||||
|
async def api_start_spec_watcher(project_id: int):
|
||||||
|
"""Start spec watcher for a project."""
|
||||||
|
try:
|
||||||
|
from app.core.spec_watcher import get_global_spec_watcher
|
||||||
|
|
||||||
|
# Get project path
|
||||||
|
db_manager = get_sqlite_manager()
|
||||||
|
project = db_manager.get_project(project_id)
|
||||||
|
if not project:
|
||||||
|
raise HTTPException(status_code=404, detail="Project not found")
|
||||||
|
|
||||||
|
spec_watcher = get_global_spec_watcher()
|
||||||
|
spec_watcher.start_project(project_id, project['path'])
|
||||||
|
|
||||||
|
return {
|
||||||
|
"project_id": project_id,
|
||||||
|
"message": "Spec watcher started",
|
||||||
|
"status": spec_watcher.get_status()
|
||||||
|
}
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Failed to start spec watcher: {e}")
|
||||||
|
raise HTTPException(status_code=500, detail=str(e))
|
||||||
|
|
||||||
|
|
||||||
|
@app.post("/api/spec-watcher/stop/{project_id}")
|
||||||
|
async def api_stop_spec_watcher(project_id: int):
|
||||||
|
"""Stop spec watcher for a project."""
|
||||||
|
try:
|
||||||
|
from app.core.spec_watcher import get_global_spec_watcher
|
||||||
|
|
||||||
|
spec_watcher = get_global_spec_watcher()
|
||||||
|
spec_watcher.stop_project(project_id)
|
||||||
|
|
||||||
|
return {
|
||||||
|
"project_id": project_id,
|
||||||
|
"message": "Spec watcher stopped",
|
||||||
|
"status": spec_watcher.get_status()
|
||||||
|
}
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Failed to stop spec watcher: {e}")
|
||||||
|
raise HTTPException(status_code=500, detail=str(e))
|
||||||
|
|
||||||
|
|
||||||
|
@app.post("/api/spec-watcher/start-all")
|
||||||
|
async def api_start_all_spec_watchers():
|
||||||
|
"""Start spec watchers for all projects."""
|
||||||
|
try:
|
||||||
|
from app.core.spec_watcher import get_global_spec_watcher
|
||||||
|
|
||||||
|
spec_watcher = get_global_spec_watcher()
|
||||||
|
spec_watcher.start_all()
|
||||||
|
|
||||||
|
return {
|
||||||
|
"message": "Spec watchers started for all projects",
|
||||||
|
"status": spec_watcher.get_status()
|
||||||
|
}
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Failed to start all spec watchers: {e}")
|
||||||
|
raise HTTPException(status_code=500, detail=str(e))
|
||||||
|
|
||||||
|
|
||||||
|
@app.get("/api/spec-watcher/status")
|
||||||
|
async def api_spec_watcher_status():
|
||||||
|
"""Get spec watcher status."""
|
||||||
|
try:
|
||||||
|
from app.core.spec_watcher import get_global_spec_watcher
|
||||||
|
|
||||||
|
spec_watcher = get_global_spec_watcher()
|
||||||
|
return {"status": spec_watcher.get_status()}
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Failed to get spec watcher status: {e}")
|
||||||
|
raise HTTPException(status_code=500, detail=str(e))
|
||||||
|
|
||||||
|
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
# SPEC TRACKING ENDPOINTS (for agent-os integration and Kanban board)
|
# SPEC TRACKING ENDPOINTS (for agent-os integration and Kanban board)
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
|
|
@ -2492,6 +2571,47 @@ async def health_check():
|
||||||
return JSONResponse(content=health_status, status_code=status_code)
|
return JSONResponse(content=health_status, status_code=status_code)
|
||||||
|
|
||||||
|
|
||||||
|
# ============================================================================
|
||||||
|
# STARTUP/SHUTDOWN EVENTS
|
||||||
|
# ============================================================================
|
||||||
|
|
||||||
|
@app.on_event("startup")
|
||||||
|
async def startup_event():
|
||||||
|
"""Run tasks on server startup."""
|
||||||
|
logger.info("🚀 Starting up Claude OS MCP Server...")
|
||||||
|
|
||||||
|
# Auto-start spec watchers for all projects
|
||||||
|
try:
|
||||||
|
from app.core.spec_watcher import get_global_spec_watcher
|
||||||
|
|
||||||
|
spec_watcher = get_global_spec_watcher()
|
||||||
|
spec_watcher.start_all()
|
||||||
|
|
||||||
|
status = spec_watcher.get_status()
|
||||||
|
if status['enabled']:
|
||||||
|
logger.info(f"✅ Spec watchers started for {status['projects_watched']} project(s)")
|
||||||
|
else:
|
||||||
|
logger.info("ℹ️ No projects found - spec watchers will start when projects are created")
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"❌ Failed to start spec watchers: {e}")
|
||||||
|
|
||||||
|
|
||||||
|
@app.on_event("shutdown")
|
||||||
|
async def shutdown_event():
|
||||||
|
"""Run tasks on server shutdown."""
|
||||||
|
logger.info("👋 Shutting down Claude OS MCP Server...")
|
||||||
|
|
||||||
|
# Stop all spec watchers
|
||||||
|
try:
|
||||||
|
from app.core.spec_watcher import get_global_spec_watcher
|
||||||
|
|
||||||
|
spec_watcher = get_global_spec_watcher()
|
||||||
|
spec_watcher.stop_all()
|
||||||
|
logger.info("✅ Spec watchers stopped")
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"❌ Failed to stop spec watchers: {e}")
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
"""Start the MCP server."""
|
"""Start the MCP server."""
|
||||||
# Validate configuration before starting
|
# Validate configuration before starting
|
||||||
|
|
|
||||||
|
|
@ -166,6 +166,88 @@ RUN /opt/claude-os/scripts/index-codebase.sh MyApp /app http://claude-os:8051
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
## Screenshot Capture Script
|
||||||
|
|
||||||
|
**`capture-screenshots.js`** - Automatically capture beautiful screenshots of the Claude OS interface using Playwright.
|
||||||
|
|
||||||
|
### Usage
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# From frontend directory
|
||||||
|
cd frontend
|
||||||
|
npm run screenshots
|
||||||
|
|
||||||
|
# Or directly
|
||||||
|
node ../scripts/capture-screenshots.js
|
||||||
|
```
|
||||||
|
|
||||||
|
### Prerequisites
|
||||||
|
|
||||||
|
1. **Services running:**
|
||||||
|
```bash
|
||||||
|
./start.sh # Starts MCP server (8051) and frontend (5173)
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **At least one project created** (e.g., Pistn)
|
||||||
|
|
||||||
|
3. **Playwright installed:**
|
||||||
|
```bash
|
||||||
|
cd frontend
|
||||||
|
npx playwright install chromium
|
||||||
|
```
|
||||||
|
|
||||||
|
### What Gets Captured
|
||||||
|
|
||||||
|
Automatically captures 9 screenshots:
|
||||||
|
|
||||||
|
1. `welcome-screen.png` - Landing page
|
||||||
|
2. `projects-list-page.png` - Projects overview
|
||||||
|
3. `project-overview-page.png` - Project details & MCP status
|
||||||
|
4. `project-kanban-page.png` - Kanban board (full page)
|
||||||
|
5. `kanban-task-detail-modal.png` - Task detail popup
|
||||||
|
6. `project-mcp-page.png` - Knowledge base management
|
||||||
|
7. `project-chat-page.png` - Chat interface
|
||||||
|
8. `project-services-dashboard-page.png` - Service monitoring
|
||||||
|
9. `mobile-welcome-screen.png` - Mobile version (375x812)
|
||||||
|
|
||||||
|
### Output
|
||||||
|
|
||||||
|
All screenshots saved to:
|
||||||
|
```
|
||||||
|
frontend/public/assets/screenshots/
|
||||||
|
```
|
||||||
|
|
||||||
|
### When to Re-capture
|
||||||
|
|
||||||
|
**Update screenshots when:**
|
||||||
|
- UI design changes
|
||||||
|
- New features added
|
||||||
|
- Before major releases
|
||||||
|
- For updated documentation
|
||||||
|
|
||||||
|
**Quick update:**
|
||||||
|
```bash
|
||||||
|
# 1. Ensure services running
|
||||||
|
./start.sh
|
||||||
|
|
||||||
|
# 2. Run screenshot capture
|
||||||
|
cd frontend && npm run screenshots
|
||||||
|
|
||||||
|
# 3. Commit updated screenshots
|
||||||
|
git add public/assets/screenshots/
|
||||||
|
git commit -m "📸 Update UI screenshots"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Configuration
|
||||||
|
|
||||||
|
Edit `scripts/capture-screenshots.js` to customize:
|
||||||
|
- Viewport size (default: 1920x1080)
|
||||||
|
- Wait times for animations
|
||||||
|
- Which pages to capture
|
||||||
|
- Headless mode for CI/CD
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## Future Scripts
|
## Future Scripts
|
||||||
|
|
||||||
Additional utility scripts will be added here:
|
Additional utility scripts will be added here:
|
||||||
|
|
@ -174,6 +256,8 @@ Additional utility scripts will be added here:
|
||||||
- `migrate-project.sh` - Migrate project between Claude OS instances
|
- `migrate-project.sh` - Migrate project between Claude OS instances
|
||||||
- `export-memories.sh` - Export project memories as markdown
|
- `export-memories.sh` - Export project memories as markdown
|
||||||
- `sync-team-knowledge.sh` - Sync knowledge bases across team
|
- `sync-team-knowledge.sh` - Sync knowledge bases across team
|
||||||
|
- `test-e2e.js` - End-to-end UI testing with Playwright
|
||||||
|
- `seed-data.js` - Seed test data for demos
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
|
||||||
168
scripts/capture-screenshots.js
Normal file
|
|
@ -0,0 +1,168 @@
|
||||||
|
/**
|
||||||
|
* Claude OS Screenshot Capture Script
|
||||||
|
*
|
||||||
|
* Automatically captures beautiful screenshots of the entire Claude OS interface
|
||||||
|
* using Playwright for documentation and marketing materials.
|
||||||
|
*
|
||||||
|
* Usage:
|
||||||
|
* node scripts/capture-screenshots.js
|
||||||
|
*
|
||||||
|
* Prerequisites:
|
||||||
|
* - Frontend running on http://localhost:5173
|
||||||
|
* - MCP server running on http://localhost:8051
|
||||||
|
* - At least one project created (e.g., Pistn)
|
||||||
|
*/
|
||||||
|
|
||||||
|
const { chromium } = require(require('path').join(__dirname, '../frontend/node_modules/playwright'));
|
||||||
|
const path = require('path');
|
||||||
|
const fs = require('fs');
|
||||||
|
|
||||||
|
// Configuration
|
||||||
|
const BASE_URL = 'http://localhost:5173';
|
||||||
|
const SCREENSHOTS_DIR = path.join(__dirname, '../frontend/public/assets/screenshots');
|
||||||
|
const VIEWPORT = { width: 1920, height: 1080 };
|
||||||
|
const WAIT_TIME = 2000; // Wait for animations/data loading
|
||||||
|
|
||||||
|
// Ensure screenshots directory exists
|
||||||
|
if (!fs.existsSync(SCREENSHOTS_DIR)) {
|
||||||
|
fs.mkdirSync(SCREENSHOTS_DIR, { recursive: true });
|
||||||
|
}
|
||||||
|
|
||||||
|
async function captureScreenshots() {
|
||||||
|
console.log('🎭 Starting Claude OS screenshot capture...\n');
|
||||||
|
|
||||||
|
const browser = await chromium.launch({
|
||||||
|
headless: false, // Set to true for CI/CD
|
||||||
|
});
|
||||||
|
|
||||||
|
const context = await browser.newContext({
|
||||||
|
viewport: VIEWPORT,
|
||||||
|
});
|
||||||
|
|
||||||
|
const page = await context.newPage();
|
||||||
|
|
||||||
|
try {
|
||||||
|
// 1. Welcome Screen
|
||||||
|
console.log('📸 Capturing: Welcome Screen...');
|
||||||
|
await page.goto(BASE_URL);
|
||||||
|
await page.waitForTimeout(WAIT_TIME);
|
||||||
|
await page.screenshot({
|
||||||
|
path: path.join(SCREENSHOTS_DIR, 'welcome-screen.png'),
|
||||||
|
fullPage: false,
|
||||||
|
});
|
||||||
|
console.log('✅ Saved: welcome-screen.png\n');
|
||||||
|
|
||||||
|
// Navigate to app
|
||||||
|
await page.click('a[href="/app"]');
|
||||||
|
await page.waitForTimeout(WAIT_TIME);
|
||||||
|
|
||||||
|
// 2. Projects List
|
||||||
|
console.log('📸 Capturing: Projects List...');
|
||||||
|
await page.screenshot({
|
||||||
|
path: path.join(SCREENSHOTS_DIR, 'projects-list-page.png'),
|
||||||
|
fullPage: false,
|
||||||
|
});
|
||||||
|
console.log('✅ Saved: projects-list-page.png\n');
|
||||||
|
|
||||||
|
// Select first project (Pistn)
|
||||||
|
const firstProject = await page.locator('.p-3.rounded-lg.border').first();
|
||||||
|
await firstProject.click();
|
||||||
|
await page.waitForTimeout(WAIT_TIME);
|
||||||
|
|
||||||
|
// 3. Project Overview
|
||||||
|
console.log('📸 Capturing: Project Overview...');
|
||||||
|
await page.screenshot({
|
||||||
|
path: path.join(SCREENSHOTS_DIR, 'project-overview-page.png'),
|
||||||
|
fullPage: false,
|
||||||
|
});
|
||||||
|
console.log('✅ Saved: project-overview-page.png\n');
|
||||||
|
|
||||||
|
// 4. Kanban Board
|
||||||
|
console.log('📸 Capturing: Kanban Board...');
|
||||||
|
await page.click('button:has-text("Kanban Board")');
|
||||||
|
await page.waitForTimeout(WAIT_TIME + 1000); // Extra time for Kanban data load
|
||||||
|
await page.screenshot({
|
||||||
|
path: path.join(SCREENSHOTS_DIR, 'project-kanban-page.png'),
|
||||||
|
fullPage: true, // Capture full Kanban board
|
||||||
|
});
|
||||||
|
console.log('✅ Saved: project-kanban-page.png\n');
|
||||||
|
|
||||||
|
// 5. Kanban - Task Detail Modal (if tasks exist)
|
||||||
|
try {
|
||||||
|
console.log('📸 Capturing: Task Detail Modal...');
|
||||||
|
const taskCard = await page.locator('.bg-cool-blue\\/10.border').first();
|
||||||
|
await taskCard.click();
|
||||||
|
await page.waitForTimeout(1000);
|
||||||
|
await page.screenshot({
|
||||||
|
path: path.join(SCREENSHOTS_DIR, 'kanban-task-detail-modal.png'),
|
||||||
|
fullPage: false,
|
||||||
|
});
|
||||||
|
console.log('✅ Saved: kanban-task-detail-modal.png\n');
|
||||||
|
|
||||||
|
// Close modal
|
||||||
|
await page.keyboard.press('Escape');
|
||||||
|
await page.waitForTimeout(500);
|
||||||
|
} catch (e) {
|
||||||
|
console.log('⚠️ No tasks found for task detail screenshot\n');
|
||||||
|
}
|
||||||
|
|
||||||
|
// 6. MCP Management
|
||||||
|
console.log('📸 Capturing: MCP Management...');
|
||||||
|
await page.click('button:has-text("MCP Management")');
|
||||||
|
await page.waitForTimeout(WAIT_TIME);
|
||||||
|
|
||||||
|
// Click on first MCP in sidebar
|
||||||
|
const firstMCP = await page.locator('.p-2.rounded.border.text-sm').first();
|
||||||
|
await firstMCP.click();
|
||||||
|
await page.waitForTimeout(WAIT_TIME);
|
||||||
|
|
||||||
|
await page.screenshot({
|
||||||
|
path: path.join(SCREENSHOTS_DIR, 'project-mcp-page.png'),
|
||||||
|
fullPage: false,
|
||||||
|
});
|
||||||
|
console.log('✅ Saved: project-mcp-page.png\n');
|
||||||
|
|
||||||
|
// 7. Chat Interface
|
||||||
|
console.log('📸 Capturing: Chat Interface...');
|
||||||
|
await page.click('button:has-text("Chat")');
|
||||||
|
await page.waitForTimeout(WAIT_TIME);
|
||||||
|
await page.screenshot({
|
||||||
|
path: path.join(SCREENSHOTS_DIR, 'project-chat-page.png'),
|
||||||
|
fullPage: false,
|
||||||
|
});
|
||||||
|
console.log('✅ Saved: project-chat-page.png\n');
|
||||||
|
|
||||||
|
// 8. Services Dashboard
|
||||||
|
console.log('📸 Capturing: Services Dashboard...');
|
||||||
|
await page.click('button:has-text("Services")');
|
||||||
|
await page.waitForTimeout(WAIT_TIME);
|
||||||
|
await page.screenshot({
|
||||||
|
path: path.join(SCREENSHOTS_DIR, 'project-services-dashboard-page.png'),
|
||||||
|
fullPage: false,
|
||||||
|
});
|
||||||
|
console.log('✅ Saved: project-services-dashboard-page.png\n');
|
||||||
|
|
||||||
|
// Bonus: Mobile screenshots (optional)
|
||||||
|
console.log('📱 Capturing mobile screenshots...');
|
||||||
|
await page.setViewportSize({ width: 375, height: 812 }); // iPhone X
|
||||||
|
|
||||||
|
await page.goto(BASE_URL);
|
||||||
|
await page.waitForTimeout(WAIT_TIME);
|
||||||
|
await page.screenshot({
|
||||||
|
path: path.join(SCREENSHOTS_DIR, 'mobile-welcome-screen.png'),
|
||||||
|
fullPage: false,
|
||||||
|
});
|
||||||
|
console.log('✅ Saved: mobile-welcome-screen.png\n');
|
||||||
|
|
||||||
|
console.log('✨ All screenshots captured successfully!\n');
|
||||||
|
console.log(`📁 Screenshots saved to: ${SCREENSHOTS_DIR}\n`);
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.error('❌ Error capturing screenshots:', error);
|
||||||
|
} finally {
|
||||||
|
await browser.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run the script
|
||||||
|
captureScreenshots().catch(console.error);
|
||||||