├── app ├── __init__.py ├── core │ ├── __init__.py │ ├── spec_status_updater.py │ ├── migrations │ │ └── 004_add_spec_tracking.sql │ └── health.py ├── utils │ └── __init__.py └── db │ └── schema.sqlite ├── mcp_server ├── __init__.py ├── tools │ └── __init__.py └── auth.py ├── frontend ├── test-results │ └── .last-run.json ├── src │ ├── pages │ │ ├── MainApp_backup.tsx │ │ └── Login.tsx │ ├── main.tsx │ ├── components │ │ ├── ProtectedRoute.tsx │ │ └── DirectoryPickerModal.tsx │ ├── lib │ │ ├── filePicker.ts │ │ ├── api.ts │ │ └── auth.tsx │ ├── App.tsx │ ├── index.css │ └── assets │ │ └── react.svg ├── public │ ├── assets │ │ ├── hero.png │ │ ├── logo.png │ │ ├── claude-os-hero.png │ │ ├── claude-os-logo.png │ │ ├── claude-os-architecture.png │ │ └── screenshots │ │ │ ├── welcome-screen.png │ │ │ ├── project-chat-page.png │ │ │ ├── project-mcp-page.png │ │ │ ├── project-kanban-page.png │ │ │ ├── projects-list-page.png │ │ │ ├── mobile-welcome-screen.png │ │ │ ├── project-overview-page.png │ │ │ ├── kanban-task-detail-modal.png │ │ │ └── project-services-dashboard-page.png │ └── vite.svg ├── postcss.config.js ├── tsconfig.json ├── .gitignore ├── index.html ├── vite.config.ts ├── playwright.config.ts ├── eslint.config.js ├── tsconfig.node.json ├── tsconfig.app.json ├── package.json ├── tailwind.config.js ├── e2e │ ├── screenshot-test.spec.ts │ └── configure-modal.spec.ts └── README.md ├── WHAT_IS_CLAUDE_OS.pdf ├── docs ├── assets │ └── og-image.png └── guides │ ├── AUTH_SETUP.md │ └── PORTS_GUIDE.md ├── tests ├── __init__.py ├── test_embeddings.py ├── README.md └── TEST_COVERAGE.md ├── templates ├── project-files │ ├── agent-os │ │ ├── .gitignore │ │ ├── config.yml.template │ │ └── README.md │ ├── .claude-os │ │ ├── .gitignore │ │ ├── config.json.template │ │ └── hooks.json.template │ └── agent-os-section.md ├── skill-library │ ├── testing │ │ └── rspec │ │ │ └── metadata.json │ ├── rails │ │ └── rails-backend │ │ │ ├── metadata.json │ │ │ └── skill.md │ ├── react │ │ └── react-patterns │ │ │ └── metadata.json │ └── general │ │ └── initialize-project │ │ └── metadata.json ├── skills │ ├── remember-this │ │ ├── save-to-mcp.sh │ │ └── SKILL.md │ └── memory │ │ └── SKILL.md ├── agents │ ├── implementer.md │ ├── spec-initializer.md │ ├── spec-writer.md │ └── implementation-verifier.md ├── commands │ ├── claude-os-save.md │ ├── claude-os-list.md │ ├── claude-os-search.md │ ├── claude-os-remember.md │ └── claude-os-export.md └── README.md ├── .github ├── ISSUE_TEMPLATE │ ├── config.yml │ ├── installation-issue.yml │ ├── feature_request.yml │ └── bug_report.yml └── workflows │ └── tests.yml ├── pytest.ini ├── restart_services.sh ├── install.sh ├── setup.sh ├── start.sh ├── scripts ├── start_mcp_server.sh ├── start_redis_workers.sh ├── entrypoint.sh ├── generate_diagnostic.sh ├── backup_claude_os.sh ├── restore_claude_os.sh ├── run_tests.sh ├── setup_native.sh └── report_error.sh ├── requirements.txt ├── .gitignore ├── .env.example ├── stop_all_services.sh ├── uninstall.sh └── cli └── claude-os-consolidate.sh /app/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app/core/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app/utils/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /mcp_server/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /mcp_server/tools/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /frontend/test-results/.last-run.json: -------------------------------------------------------------------------------- 1 | { 2 | "status": "passed", 3 | "failedTests": [] 4 | } -------------------------------------------------------------------------------- /WHAT_IS_CLAUDE_OS.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brobertsaz/claude-os/HEAD/WHAT_IS_CLAUDE_OS.pdf -------------------------------------------------------------------------------- /frontend/src/pages/MainApp_backup.tsx: -------------------------------------------------------------------------------- 1 | // Backup of old MainApp - can be deleted later 2 | 3 | -------------------------------------------------------------------------------- /docs/assets/og-image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brobertsaz/claude-os/HEAD/docs/assets/og-image.png -------------------------------------------------------------------------------- /frontend/public/assets/hero.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brobertsaz/claude-os/HEAD/frontend/public/assets/hero.png -------------------------------------------------------------------------------- /frontend/public/assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brobertsaz/claude-os/HEAD/frontend/public/assets/logo.png -------------------------------------------------------------------------------- /frontend/postcss.config.js: -------------------------------------------------------------------------------- 1 | export default { 2 | plugins: { 3 | tailwindcss: {}, 4 | autoprefixer: {}, 5 | }, 6 | } 7 | 8 | -------------------------------------------------------------------------------- /frontend/public/assets/claude-os-hero.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brobertsaz/claude-os/HEAD/frontend/public/assets/claude-os-hero.png -------------------------------------------------------------------------------- /frontend/public/assets/claude-os-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brobertsaz/claude-os/HEAD/frontend/public/assets/claude-os-logo.png -------------------------------------------------------------------------------- /tests/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | Claude OS Test Suite 3 | 4 | Comprehensive tests for all components of the Claude OS RAG system. 5 | """ 6 | 7 | -------------------------------------------------------------------------------- /frontend/public/assets/claude-os-architecture.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brobertsaz/claude-os/HEAD/frontend/public/assets/claude-os-architecture.png -------------------------------------------------------------------------------- /frontend/public/assets/screenshots/welcome-screen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brobertsaz/claude-os/HEAD/frontend/public/assets/screenshots/welcome-screen.png -------------------------------------------------------------------------------- /frontend/public/assets/screenshots/project-chat-page.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brobertsaz/claude-os/HEAD/frontend/public/assets/screenshots/project-chat-page.png -------------------------------------------------------------------------------- /frontend/public/assets/screenshots/project-mcp-page.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brobertsaz/claude-os/HEAD/frontend/public/assets/screenshots/project-mcp-page.png -------------------------------------------------------------------------------- /frontend/public/assets/screenshots/project-kanban-page.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brobertsaz/claude-os/HEAD/frontend/public/assets/screenshots/project-kanban-page.png -------------------------------------------------------------------------------- /frontend/public/assets/screenshots/projects-list-page.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brobertsaz/claude-os/HEAD/frontend/public/assets/screenshots/projects-list-page.png -------------------------------------------------------------------------------- /frontend/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "files": [], 3 | "references": [ 4 | { "path": "./tsconfig.app.json" }, 5 | { "path": "./tsconfig.node.json" } 6 | ] 7 | } 8 | -------------------------------------------------------------------------------- /frontend/public/assets/screenshots/mobile-welcome-screen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brobertsaz/claude-os/HEAD/frontend/public/assets/screenshots/mobile-welcome-screen.png -------------------------------------------------------------------------------- /frontend/public/assets/screenshots/project-overview-page.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brobertsaz/claude-os/HEAD/frontend/public/assets/screenshots/project-overview-page.png -------------------------------------------------------------------------------- /frontend/public/assets/screenshots/kanban-task-detail-modal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brobertsaz/claude-os/HEAD/frontend/public/assets/screenshots/kanban-task-detail-modal.png -------------------------------------------------------------------------------- /frontend/public/assets/screenshots/project-services-dashboard-page.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brobertsaz/claude-os/HEAD/frontend/public/assets/screenshots/project-services-dashboard-page.png -------------------------------------------------------------------------------- /templates/project-files/agent-os/.gitignore: -------------------------------------------------------------------------------- 1 | # Agent-OS state files (personal, not shared) 2 | .agent-os-state.json 3 | *.tmp 4 | *.log 5 | 6 | # Spec work in progress 7 | specs/*/planning/*.tmp 8 | specs/*/implementation/*.tmp 9 | -------------------------------------------------------------------------------- /frontend/src/main.tsx: -------------------------------------------------------------------------------- 1 | import { StrictMode } from 'react' 2 | import { createRoot } from 'react-dom/client' 3 | import './index.css' 4 | import App from './App.tsx' 5 | 6 | createRoot(document.getElementById('root')!).render( 7 | 8 | 9 | , 10 | ) 11 | -------------------------------------------------------------------------------- /templates/project-files/.claude-os/.gitignore: -------------------------------------------------------------------------------- 1 | # Claude OS State Files - These should NOT be committed 2 | claude-os-state.json 3 | .index_state 4 | .commit_count 5 | 6 | # Hooks can be committed if they're project-specific 7 | # hooks.json 8 | 9 | # Project profile can be committed 10 | # project-profile/ 11 | -------------------------------------------------------------------------------- /templates/skill-library/testing/rspec/metadata.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "rspec", 3 | "description": "RSpec testing patterns for Ruby/Rails including unit tests, request specs, factories, shared examples, and best practices.", 4 | "category": "testing", 5 | "tags": ["ruby", "rails", "rspec", "testing", "tdd", "factory-bot"], 6 | "version": "1.0.0" 7 | } 8 | -------------------------------------------------------------------------------- /frontend/.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | dist 12 | dist-ssr 13 | *.local 14 | 15 | # Editor directories and files 16 | .vscode/* 17 | !.vscode/extensions.json 18 | .idea 19 | .DS_Store 20 | *.suo 21 | *.ntvs* 22 | *.njsproj 23 | *.sln 24 | *.sw? 25 | -------------------------------------------------------------------------------- /templates/skill-library/rails/rails-backend/metadata.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "rails-backend", 3 | "description": "Rails backend patterns including service objects, ActiveRecord best practices, migrations, API endpoints, and background jobs.", 4 | "category": "rails", 5 | "tags": ["ruby", "rails", "backend", "api", "activerecord", "service-objects"], 6 | "version": "1.0.0" 7 | } 8 | -------------------------------------------------------------------------------- /templates/skill-library/react/react-patterns/metadata.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-patterns", 3 | "description": "Modern React patterns including hooks, TypeScript, state management, forms, error boundaries, and performance optimization.", 4 | "category": "react", 5 | "tags": ["react", "typescript", "hooks", "frontend", "components", "state-management"], 6 | "version": "1.0.0" 7 | } 8 | -------------------------------------------------------------------------------- /templates/skill-library/general/initialize-project/metadata.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "initialize-project", 3 | "description": "Analyze a project's codebase and documentation to generate coding standards, architecture docs, and development practices. Perfect for new project onboarding.", 4 | "category": "general", 5 | "tags": ["onboarding", "analysis", "documentation", "setup"], 6 | "version": "1.0.0" 7 | } 8 | -------------------------------------------------------------------------------- /frontend/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Claude OS | AI-Assisted Development with Persistent Context 8 | 9 | 10 |
11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /templates/project-files/agent-os/config.yml.template: -------------------------------------------------------------------------------- 1 | version: 2.1.0 2 | last_compiled: {{TIMESTAMP}} 3 | 4 | # ================================================ 5 | # Compiled with the following settings: 6 | # 7 | # To change these settings, run ~/agent-os/scripts/project-update.sh to re-compile your project with the new settings. 8 | # ================================================ 9 | profile: default 10 | claude_code_commands: true 11 | use_claude_code_subagents: true 12 | agent_os_commands: false 13 | standards_as_claude_code_skills: true 14 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: true 2 | contact_links: 3 | - name: Documentation 4 | url: https://github.com/brobertsaz/claude-os/blob/main/README.md 5 | about: Check out the documentation first 6 | - name: Start Scripts Guide 7 | url: https://github.com/brobertsaz/claude-os/blob/main/START_SCRIPTS_GUIDE.md 8 | about: Learn about start.sh vs start_all_services.sh 9 | - name: Backup & Restore Guide 10 | url: https://github.com/brobertsaz/claude-os/blob/main/BACKUP_RESTORE_GUIDE.md 11 | about: How to backup and restore your data 12 | -------------------------------------------------------------------------------- /frontend/vite.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vite' 2 | import react from '@vitejs/plugin-react' 3 | 4 | // https://vite.dev/config/ 5 | export default defineConfig({ 6 | plugins: [react()], 7 | server: { 8 | host: true, 9 | allowedHosts: [ 10 | 'localhost', 11 | '.ngrok-free.app', 12 | 'daa65fe0204a.ngrok-free.app' 13 | ], 14 | proxy: { 15 | '/api': { 16 | target: 'http://localhost:8051', 17 | changeOrigin: true, 18 | }, 19 | '/mcp': { 20 | target: 'http://localhost:8051', 21 | changeOrigin: true, 22 | }, 23 | }, 24 | }, 25 | }) 26 | -------------------------------------------------------------------------------- /pytest.ini: -------------------------------------------------------------------------------- 1 | [pytest] 2 | testpaths = tests 3 | python_files = test_*.py 4 | python_classes = Test* 5 | python_functions = test_* 6 | addopts = 7 | -v 8 | --strict-markers 9 | --tb=short 10 | --cov=app 11 | --cov-report=term-missing 12 | --cov-report=html 13 | markers = 14 | unit: Unit tests (fast, no external dependencies) 15 | integration: Integration tests (require database, Ollama) 16 | slow: Slow tests (may take several seconds) 17 | embeddings: Tests involving embedding generation 18 | vector: Tests involving vector operations 19 | rag: Tests involving RAG engine 20 | api: Tests involving API endpoints 21 | 22 | -------------------------------------------------------------------------------- /frontend/playwright.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig, devices } from '@playwright/test'; 2 | 3 | export default defineConfig({ 4 | testDir: './e2e', 5 | fullyParallel: true, 6 | forbidOnly: !!process.env.CI, 7 | retries: process.env.CI ? 2 : 0, 8 | workers: process.env.CI ? 1 : undefined, 9 | reporter: 'html', 10 | use: { 11 | baseURL: 'http://localhost:5173', 12 | trace: 'on-first-retry', 13 | screenshot: 'only-on-failure', 14 | }, 15 | projects: [ 16 | { 17 | name: 'chromium', 18 | use: { ...devices['Desktop Chrome'] }, 19 | }, 20 | ], 21 | webServer: { 22 | command: 'npm run dev', 23 | url: 'http://localhost:5173', 24 | reuseExistingServer: true, 25 | }, 26 | }); 27 | -------------------------------------------------------------------------------- /frontend/eslint.config.js: -------------------------------------------------------------------------------- 1 | import js from '@eslint/js' 2 | import globals from 'globals' 3 | import reactHooks from 'eslint-plugin-react-hooks' 4 | import reactRefresh from 'eslint-plugin-react-refresh' 5 | import tseslint from 'typescript-eslint' 6 | import { defineConfig, globalIgnores } from 'eslint/config' 7 | 8 | export default defineConfig([ 9 | globalIgnores(['dist']), 10 | { 11 | files: ['**/*.{ts,tsx}'], 12 | extends: [ 13 | js.configs.recommended, 14 | tseslint.configs.recommended, 15 | reactHooks.configs['recommended-latest'], 16 | reactRefresh.configs.vite, 17 | ], 18 | languageOptions: { 19 | ecmaVersion: 2020, 20 | globals: globals.browser, 21 | }, 22 | }, 23 | ]) 24 | -------------------------------------------------------------------------------- /frontend/tsconfig.node.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", 4 | "target": "ES2023", 5 | "lib": ["ES2023"], 6 | "module": "ESNext", 7 | "types": ["node"], 8 | "skipLibCheck": true, 9 | 10 | /* Bundler mode */ 11 | "moduleResolution": "bundler", 12 | "allowImportingTsExtensions": true, 13 | "verbatimModuleSyntax": true, 14 | "moduleDetection": "force", 15 | "noEmit": true, 16 | 17 | /* Linting */ 18 | "strict": true, 19 | "noUnusedLocals": true, 20 | "noUnusedParameters": true, 21 | "erasableSyntaxOnly": true, 22 | "noFallthroughCasesInSwitch": true, 23 | "noUncheckedSideEffectImports": true 24 | }, 25 | "include": ["vite.config.ts"] 26 | } 27 | -------------------------------------------------------------------------------- /templates/project-files/.claude-os/config.json.template: -------------------------------------------------------------------------------- 1 | { 2 | "project_name": "{{PROJECT_NAME}}", 3 | "claude_os_url": "{{CLAUDE_OS_URL}}", 4 | "knowledge_bases": { 5 | "memories": "{{PROJECT_NAME}}-project_memories", 6 | "profile": "{{PROJECT_NAME}}-project_profile", 7 | "index": "{{PROJECT_NAME}}-project_index", 8 | "docs": "{{PROJECT_NAME}}-knowledge_docs" 9 | }, 10 | "docs_settings": { 11 | "watch_paths": {{DOCS_PATHS}}, 12 | "auto_ingest_patterns": ["*.md", "*.txt", "*.pdf"], 13 | "exclude_patterns": ["node_modules", ".git", "vendor", "build", "dist"] 14 | }, 15 | "tech_stack": "{{TECH_STACK}}", 16 | "database": "{{DATABASE}}", 17 | "dev_environment": "{{DEV_ENVIRONMENT}}", 18 | "created_at": "{{CREATED_AT}}", 19 | "claude_os_version": "1.0.0" 20 | } 21 | -------------------------------------------------------------------------------- /frontend/tsconfig.app.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", 4 | "target": "ES2022", 5 | "useDefineForClassFields": true, 6 | "lib": ["ES2022", "DOM", "DOM.Iterable"], 7 | "module": "ESNext", 8 | "types": ["vite/client"], 9 | "skipLibCheck": true, 10 | 11 | /* Bundler mode */ 12 | "moduleResolution": "bundler", 13 | "allowImportingTsExtensions": true, 14 | "verbatimModuleSyntax": true, 15 | "moduleDetection": "force", 16 | "noEmit": true, 17 | "jsx": "react-jsx", 18 | 19 | /* Linting */ 20 | "strict": true, 21 | "noUnusedLocals": true, 22 | "noUnusedParameters": true, 23 | "erasableSyntaxOnly": true, 24 | "noFallthroughCasesInSwitch": true, 25 | "noUncheckedSideEffectImports": true 26 | }, 27 | "include": ["src"] 28 | } 29 | -------------------------------------------------------------------------------- /restart_services.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Colors for output 4 | RED='\033[0;31m' 5 | GREEN='\033[0;32m' 6 | YELLOW='\033[1;33m' 7 | BLUE='\033[0;34m' 8 | NC='\033[0m' # No Color 9 | 10 | echo -e "${BLUE}==================================================" 11 | echo "🔄 Claude OS - Restarting All Services" 12 | echo "=================================================${NC}" 13 | echo "" 14 | 15 | # Get the project directory 16 | PROJECT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" 17 | 18 | # Stop services 19 | echo -e "${YELLOW}Stopping existing services...${NC}" 20 | "$PROJECT_DIR/stop_all_services.sh" 21 | 22 | # Wait a bit for ports to be released and cleanup 23 | echo -e "${YELLOW}Cleaning up...${NC}" 24 | sleep 3 25 | 26 | # Start services 27 | echo "" 28 | echo -e "${YELLOW}Starting all services fresh...${NC}" 29 | echo "" 30 | "$PROJECT_DIR/start_all_services.sh" 31 | -------------------------------------------------------------------------------- /templates/project-files/.claude-os/hooks.json.template: -------------------------------------------------------------------------------- 1 | { 2 | "hooks": { 3 | "pre_commit": { 4 | "enabled": false, 5 | "commands": [] 6 | }, 7 | "post_commit": { 8 | "enabled": false, 9 | "commands": [] 10 | }, 11 | "pre_session_start": { 12 | "enabled": true, 13 | "commands": [ 14 | { 15 | "name": "Load Project Context", 16 | "action": "search_memories", 17 | "kb_name": "{{PROJECT_NAME}}-project_memories", 18 | "query": "recent work context" 19 | } 20 | ] 21 | }, 22 | "post_session_end": { 23 | "enabled": true, 24 | "commands": [ 25 | { 26 | "name": "Save Session Summary", 27 | "action": "save_to_memories", 28 | "kb_name": "{{PROJECT_NAME}}-project_memories" 29 | } 30 | ] 31 | } 32 | }, 33 | "project_name": "{{PROJECT_NAME}}", 34 | "version": "1.0.0" 35 | } 36 | -------------------------------------------------------------------------------- /install.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # ═══════════════════════════════════════════════════════════════════════════ 3 | # DEPRECATED: This script now redirects to setup-claude-os.sh 4 | # ═══════════════════════════════════════════════════════════════════════════ 5 | # 6 | # For the best experience, run: 7 | # ./setup-claude-os.sh 8 | # 9 | # This alias exists for backwards compatibility with existing documentation. 10 | # ═══════════════════════════════════════════════════════════════════════════ 11 | 12 | SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" 13 | 14 | echo "" 15 | echo "┌────────────────────────────────────────────────────────────────┐" 16 | echo "│ ℹ️ install.sh is now setup-claude-os.sh │" 17 | echo "│ │" 18 | echo "│ Redirecting to the new unified installer... │" 19 | echo "└────────────────────────────────────────────────────────────────┘" 20 | echo "" 21 | sleep 1 22 | 23 | exec "${SCRIPT_DIR}/setup-claude-os.sh" "$@" 24 | -------------------------------------------------------------------------------- /setup.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # ═══════════════════════════════════════════════════════════════════════════ 3 | # DEPRECATED: This script now redirects to setup-claude-os.sh 4 | # ═══════════════════════════════════════════════════════════════════════════ 5 | # 6 | # For the best experience, run: 7 | # ./setup-claude-os.sh 8 | # 9 | # This alias exists for backwards compatibility with existing documentation. 10 | # ═══════════════════════════════════════════════════════════════════════════ 11 | 12 | SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" 13 | 14 | echo "" 15 | echo "┌────────────────────────────────────────────────────────────────┐" 16 | echo "│ ℹ️ setup.sh is now setup-claude-os.sh │" 17 | echo "│ │" 18 | echo "│ Redirecting to the new unified installer... │" 19 | echo "└────────────────────────────────────────────────────────────────┘" 20 | echo "" 21 | sleep 1 22 | 23 | exec "${SCRIPT_DIR}/setup-claude-os.sh" "$@" 24 | -------------------------------------------------------------------------------- /app/core/spec_status_updater.py: -------------------------------------------------------------------------------- 1 | """ 2 | Utility to update spec statuses based on completion percentage. 3 | """ 4 | 5 | import sqlite3 6 | from app.core.config import Config 7 | 8 | 9 | def update_all_spec_statuses(db_path: str = None): 10 | """Update status for all specs based on completion.""" 11 | db_path = db_path or Config.SQLITE_DB_PATH 12 | conn = sqlite3.connect(db_path) 13 | cursor = conn.cursor() 14 | 15 | # Update all spec statuses 16 | cursor.execute(""" 17 | UPDATE specs SET 18 | status = CASE 19 | WHEN total_tasks = 0 THEN 'planning' 20 | WHEN completed_tasks = 0 THEN 'planning' 21 | WHEN completed_tasks = total_tasks THEN 'completed' 22 | ELSE 'in_progress' 23 | END, 24 | updated_at = CURRENT_TIMESTAMP 25 | """) 26 | 27 | rows_updated = cursor.rowcount 28 | conn.commit() 29 | conn.close() 30 | 31 | return {"updated": rows_updated} 32 | 33 | 34 | if __name__ == "__main__": 35 | result = update_all_spec_statuses() 36 | print(f"Updated {result['updated']} specs") 37 | -------------------------------------------------------------------------------- /frontend/src/components/ProtectedRoute.tsx: -------------------------------------------------------------------------------- 1 | import { Navigate } from 'react-router-dom'; 2 | import { useAuth } from '../lib/auth'; 3 | 4 | export default function ProtectedRoute({ children }: { children: React.ReactNode }) { 5 | const { isAuthenticated, isAuthEnabled, isLoading } = useAuth(); 6 | 7 | // Show loading state while checking auth 8 | if (isLoading) { 9 | return ( 10 |
11 |
12 |
13 |

Loading...

14 |
15 |
16 | ); 17 | } 18 | 19 | // If auth is disabled, allow access 20 | if (!isAuthEnabled) { 21 | return <>{children}; 22 | } 23 | 24 | // If auth is enabled but user not authenticated, redirect to login 25 | if (!isAuthenticated) { 26 | return ; 27 | } 28 | 29 | // User is authenticated, show the protected content 30 | return <>{children}; 31 | } 32 | -------------------------------------------------------------------------------- /frontend/src/lib/filePicker.ts: -------------------------------------------------------------------------------- 1 | export interface CommonPath { 2 | label: string; 3 | path: string; 4 | description?: string; 5 | } 6 | 7 | export function getCommonProjectPaths(): CommonPath[] { 8 | return [ 9 | { label: 'Home', path: '~', description: 'Your home directory' }, 10 | { label: 'Documents', path: '~/Documents', description: 'Documents folder' }, 11 | { label: 'Projects', path: '~/Projects', description: 'Common projects folder' }, 12 | { label: 'Sites', path: '~/sites', description: 'Web projects' }, 13 | { label: 'Code', path: '~/code', description: 'Code repositories' }, 14 | { label: 'Desktop', path: '~/Desktop', description: 'Desktop folder' }, 15 | ]; 16 | } 17 | 18 | export function formatPathForDisplay(path: string): string { 19 | if (!path) return ''; 20 | 21 | // Replace home directory with ~ 22 | const homeDir = '/home/' + (typeof window !== 'undefined' ? 'user' : 'user'); 23 | if (path.startsWith(homeDir)) { 24 | return path.replace(homeDir, '~'); 25 | } 26 | 27 | // Shorten long paths 28 | if (path.length > 50) { 29 | const parts = path.split('/'); 30 | if (parts.length > 4) { 31 | return `${parts[0]}/${parts[1]}/.../${parts[parts.length - 2]}/${parts[parts.length - 1]}`; 32 | } 33 | } 34 | 35 | return path; 36 | } 37 | -------------------------------------------------------------------------------- /start.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Start Claude OS services 3 | 4 | CLAUDE_OS_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" 5 | cd "$CLAUDE_OS_DIR" 6 | 7 | echo "🚀 Starting Claude OS..." 8 | echo "" 9 | 10 | # Activate virtual environment 11 | source venv/bin/activate 12 | 13 | # Start the MCP server 14 | echo "📡 Starting MCP server on http://localhost:8051" 15 | python3 mcp_server/server.py & 16 | MCP_PID=$! 17 | 18 | echo "✅ Claude OS MCP Server is running!" 19 | echo "" 20 | echo " 📡 MCP Server: http://localhost:8051" 21 | echo " (For Claude Code integration - do NOT open in browser)" 22 | echo "" 23 | echo "To stop MCP server: kill \$MCP_PID or press Ctrl+C" 24 | echo "" 25 | echo "════════════════════════════════════════" 26 | echo "💡 Want the full experience?" 27 | echo "════════════════════════════════════════" 28 | echo "" 29 | echo "This script only starts the MCP server." 30 | echo "" 31 | echo "To start ALL services (MCP + Frontend + Workers):" 32 | echo " ./start_all_services.sh" 33 | echo "" 34 | echo "This will give you:" 35 | echo " • MCP Server (port 8051) - For Claude Code" 36 | echo " • Web UI (port 5173) - Visual interface" 37 | echo " • Redis + Workers - Real-time learning" 38 | echo " • Ollama - Local AI models" 39 | echo "" 40 | 41 | # Wait for server to exit 42 | wait $MCP_PID 43 | -------------------------------------------------------------------------------- /scripts/start_mcp_server.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Start the MCP server natively on macOS with Metal GPU acceleration 3 | 4 | echo "🚀 Starting Claude OS MCP Server (Native, no Docker)" 5 | echo "==================================================" 6 | echo "" 7 | echo "System Info:" 8 | echo " - CPU Cores: $(sysctl -n hw.ncpu)" 9 | echo " - RAM: $(sysctl -n hw.memsize | awk '{print $0/1024/1024/1024 " GB"}')" 10 | echo " - Ollama: $(which ollama)" 11 | echo "" 12 | 13 | # Get the project directory 14 | PROJECT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" 15 | 16 | # Check if Ollama is running 17 | if ! curl -s http://localhost:11434/api/tags &> /dev/null; then 18 | echo "❌ Ollama is not running!" 19 | echo "Start Ollama with: brew services start ollama" 20 | exit 1 21 | fi 22 | 23 | echo "✅ Ollama is running" 24 | echo "" 25 | 26 | # Activate venv 27 | source "$PROJECT_DIR/venv/bin/activate" 28 | 29 | echo "" 30 | echo "Starting MCP Server..." 31 | echo "📡 MCP Server will be available at: http://localhost:8051" 32 | echo "" 33 | echo "Press Ctrl+C to stop the server" 34 | echo "" 35 | 36 | # Run the server from the project root with correct database path 37 | export SQLITE_DB_PATH="$PROJECT_DIR/data/claude-os.db" 38 | echo "Database: $SQLITE_DB_PATH" 39 | echo "" 40 | 41 | cd "$PROJECT_DIR/mcp_server" 42 | python3 server.py 43 | -------------------------------------------------------------------------------- /frontend/src/App.tsx: -------------------------------------------------------------------------------- 1 | import { BrowserRouter, Routes, Route, Navigate } from 'react-router-dom'; 2 | import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; 3 | import { AuthProvider } from './lib/auth'; 4 | import Welcome from './pages/Welcome'; 5 | import MainApp from './pages/MainApp'; 6 | import Login from './pages/Login'; 7 | import ProtectedRoute from './components/ProtectedRoute'; 8 | 9 | const queryClient = new QueryClient({ 10 | defaultOptions: { 11 | queries: { 12 | refetchOnWindowFocus: false, 13 | retry: 1, 14 | }, 15 | }, 16 | }); 17 | 18 | function App() { 19 | return ( 20 | 21 | 22 | 23 | 24 | } /> 25 | 27 | 28 | 29 | } /> 30 | 32 | 33 | 34 | } /> 35 | } /> 36 | 37 | 38 | 39 | 40 | ); 41 | } 42 | 43 | export default App; 44 | -------------------------------------------------------------------------------- /frontend/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "frontend", 3 | "private": true, 4 | "version": "0.0.0", 5 | "type": "module", 6 | "scripts": { 7 | "dev": "vite", 8 | "build": "tsc -b && vite build", 9 | "lint": "eslint .", 10 | "preview": "vite preview", 11 | "screenshots": "node ../scripts/capture-screenshots.js" 12 | }, 13 | "dependencies": { 14 | "@tanstack/react-query": "^5.90.5", 15 | "@types/react-syntax-highlighter": "^15.5.13", 16 | "axios": "^1.12.2", 17 | "framer-motion": "^12.23.24", 18 | "lucide-react": "^0.546.0", 19 | "react": "^19.1.1", 20 | "react-dom": "^19.1.1", 21 | "react-markdown": "^10.1.0", 22 | "react-router-dom": "^7.9.4", 23 | "react-syntax-highlighter": "^16.0.0" 24 | }, 25 | "devDependencies": { 26 | "@eslint/js": "^9.36.0", 27 | "@playwright/test": "^1.56.1", 28 | "@tailwindcss/typography": "^0.5.19", 29 | "@types/node": "^24.6.0", 30 | "@types/react": "^19.1.16", 31 | "@types/react-dom": "^19.1.9", 32 | "@vitejs/plugin-react": "^5.0.4", 33 | "autoprefixer": "^10.4.21", 34 | "eslint": "^9.36.0", 35 | "eslint-plugin-react-hooks": "^5.2.0", 36 | "eslint-plugin-react-refresh": "^0.4.22", 37 | "globals": "^16.4.0", 38 | "postcss": "^8.5.6", 39 | "tailwindcss": "^3.4.18", 40 | "typescript": "~5.9.3", 41 | "typescript-eslint": "^8.45.0", 42 | "vite": "^7.1.7" 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /frontend/public/vite.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | # LlamaIndex and RAG 2 | llama-index>=0.10.0 3 | llama-index-llms-ollama>=0.1.0 4 | llama-index-embeddings-ollama>=0.1.0 5 | 6 | # Vector Database (SQLite-based) 7 | sqlite-vec>=0.1.0 8 | numpy>=1.24.0 9 | 10 | # Tree-sitter for fast structural indexing 11 | # NOTE: tree-sitter-languages 1.10.x is incompatible with tree-sitter 0.21+ 12 | # The 0.21+ API changed Parser() and Language() constructors breaking the library 13 | tree-sitter>=0.20.0,<0.21.0 14 | tree-sitter-languages>=1.10.0 # Pre-built binaries for 40+ languages 15 | networkx>=3.2.1 # For dependency graphs and PageRank 16 | 17 | # File system watching 18 | watchdog>=3.0.0 19 | 20 | # Document Processing 21 | pymupdf>=1.23.0 22 | 23 | # Reranking and Hybrid Search 24 | sentence-transformers>=2.2.0 25 | rank-bm25>=0.2.2 26 | 27 | # MCP Server 28 | mcp>=1.0.0 29 | fastapi>=0.104.0 30 | uvicorn>=0.24.0 31 | pydantic>=2.0.0 32 | slowapi>=0.1.9 # Rate limiting 33 | 34 | # Authentication 35 | passlib[bcrypt]>=1.7.4 36 | bcrypt>=4.0.0,<5.0.0 # bcrypt 5.0+ has compatibility issues with passlib 1.7.4 37 | python-jose[cryptography]>=3.3.0 38 | python-multipart>=0.0.6 39 | 40 | # Utilities 41 | python-dotenv>=1.0.0 42 | requests>=2.31.0 43 | 44 | # Real-time Learning System 45 | redis>=5.0.0 # Redis client for pub/sub and caching 46 | rq>=1.14.0 # Job queue (Python equivalent of Sidekiq) 47 | 48 | # Testing 49 | pytest>=7.4.0 50 | pytest-asyncio>=0.21.0 51 | pytest-cov>=4.1.0 52 | pytest-mock>=3.12.0 53 | httpx>=0.25.0 # For testing FastAPI endpoints 54 | faker>=20.0.0 # For generating test data 55 | -------------------------------------------------------------------------------- /templates/skills/remember-this/save-to-mcp.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # save-to-mcp.sh - Save context to Claude OS 4 | # Usage: save-to-mcp.sh "Document Title" "Content" "KB Name (optional)" "Category (optional)" 5 | 6 | TITLE="${1:-Captured Context}" 7 | CONTENT="${2:-}" 8 | KB_NAME="${3:-project_memories}" 9 | CATEGORY="${4:-General}" 10 | 11 | # Sanitize KB name for URL 12 | KB_ENCODED=$(echo "$KB_NAME" | sed 's/ /%20/g') 13 | 14 | # Create timestamp 15 | TIMESTAMP=$(date -u +"%Y-%m-%dT%H:%M:%SZ") 16 | DATE=$(date +"%Y-%m-%d") 17 | 18 | # Create document 19 | DOC_CONTENT=$(cat < "$DOC_PATH" 43 | 44 | # Upload to Claude OS 45 | API_URL="http://localhost:8051" 46 | RESPONSE=$(curl -s -X POST \ 47 | "$API_URL/api/kb/$KB_ENCODED/upload" \ 48 | -F "file=@$DOC_PATH" \ 49 | -w "\n%{http_code}") 50 | 51 | HTTP_CODE=$(echo "$RESPONSE" | tail -n 1) 52 | 53 | # Check response 54 | if [[ "$HTTP_CODE" =~ ^(200|201)$ ]]; then 55 | echo "✅ Saved to Claude OS" 56 | echo "📁 KB: $KB_NAME" 57 | echo "📄 Title: $TITLE" 58 | echo "🏷️ Category: $CATEGORY" 59 | echo "💾 Local: $DOC_PATH" 60 | exit 0 61 | else 62 | echo "❌ Failed to save (HTTP $HTTP_CODE)" 63 | echo "Response: $(echo "$RESPONSE" | sed '$d')" 64 | exit 1 65 | fi 66 | -------------------------------------------------------------------------------- /frontend/tailwind.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('tailwindcss').Config} */ 2 | export default { 3 | content: [ 4 | "./index.html", 5 | "./src/**/*.{js,ts,jsx,tsx}", 6 | ], 7 | plugins: [ 8 | require('@tailwindcss/typography'), 9 | ], 10 | theme: { 11 | extend: { 12 | colors: { 13 | // Claude OS Design Guide colors 14 | 'deep-night': '#0A0E1A', 15 | 'electric-teal': '#00FFFF', 16 | 'blaze-orange': '#FF8C00', 17 | 'cool-blue': '#4D94FF', 18 | 'light-grey': '#C0C0C0', 19 | // Archon-inspired accent colors 20 | 'archon-purple': 'hsl(271, 91%, 65%)', 21 | 'archon-pink': 'hsl(330, 90%, 65%)', 22 | }, 23 | fontFamily: { 24 | mono: ['"JetBrains Mono"', 'monospace'], 25 | }, 26 | animation: { 27 | 'float': 'float 3s ease-in-out infinite', 28 | 'pulse-glow': 'pulse-glow 8s ease-in-out infinite', 29 | 'gradient': 'gradient 8s linear infinite', 30 | }, 31 | keyframes: { 32 | float: { 33 | '0%, 100%': { transform: 'translateY(0px)' }, 34 | '50%': { transform: 'translateY(-20px)' }, 35 | }, 36 | 'pulse-glow': { 37 | '0%, 100%': { transform: 'scale(1)', opacity: '0.5' }, 38 | '50%': { transform: 'scale(1.1)', opacity: '0.8' }, 39 | }, 40 | gradient: { 41 | '0%, 100%': { backgroundPosition: '0% 50%' }, 42 | '50%': { backgroundPosition: '100% 50%' }, 43 | }, 44 | }, 45 | backgroundSize: { 46 | '200': '200% 200%', 47 | }, 48 | }, 49 | }, 50 | plugins: [], 51 | } 52 | 53 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Python 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | *.so 6 | .Python 7 | build/ 8 | develop-eggs/ 9 | dist/ 10 | downloads/ 11 | eggs/ 12 | .eggs/ 13 | lib/ 14 | lib64/ 15 | !frontend/src/lib/ 16 | parts/ 17 | sdist/ 18 | var/ 19 | wheels/ 20 | *.egg-info/ 21 | .installed.cfg 22 | *.egg 23 | 24 | # Virtual Environment 25 | venv/ 26 | venv_*/ 27 | env/ 28 | ENV/ 29 | .venv 30 | 31 | # Node.js / React / Frontend 32 | node_modules/ 33 | frontend/dist/ 34 | frontend/.vite/ 35 | *.tsbuildinfo 36 | npm-debug.log* 37 | yarn-debug.log* 38 | yarn-error.log* 39 | pnpm-debug.log* 40 | .npm 41 | .yarn 42 | frontend-dev.log 43 | 44 | # IDE 45 | .vscode/ 46 | .idea/ 47 | *.swp 48 | *.swo 49 | *~ 50 | .DS_Store 51 | 52 | # Environment Variables 53 | .env 54 | *.backup.* 55 | 56 | # Data Directories 57 | data/chroma/ 58 | data/uploads/ 59 | data/ollama/ 60 | data/postgres/ 61 | *.db 62 | *.sqlite 63 | # Exception: Schema file should be tracked 64 | !app/db/schema.sqlite 65 | 66 | # Docker 67 | .dockerignore 68 | 69 | # Logs 70 | *.log 71 | logs/ 72 | 73 | # Streamlit 74 | .streamlit/secrets.toml 75 | 76 | # Temporary Files 77 | tmp/ 78 | temp/ 79 | *.tmp 80 | 81 | # Backups (contain sensitive data) 82 | backups/ 83 | 84 | # OS 85 | Thumbs.db 86 | 87 | claude-os-state.json 88 | claude-os-config.json 89 | claude-os-triggers.json 90 | 91 | # Test artifacts 92 | htmlcov/ 93 | .coverage 94 | .pytest_cache/ 95 | frontend/e2e/screenshots/ 96 | frontend/playwright-report/ 97 | frontend/test-results/ 98 | 99 | # Internal docs (not for public repo) 100 | internal_docs/ 101 | 102 | # Export files (contain project-specific data) 103 | exports/ 104 | 105 | # Marketing materials (not for distribution) 106 | brochure.html 107 | presentation.html 108 | 109 | # Private directory (not for public repo) 110 | our_stuff/ 111 | .coverage -------------------------------------------------------------------------------- /frontend/e2e/screenshot-test.spec.ts: -------------------------------------------------------------------------------- 1 | import { test, expect } from '@playwright/test'; 2 | 3 | test('Take screenshot of configure modal', async ({ page }) => { 4 | // Navigate to the app 5 | await page.goto('/app'); 6 | await page.waitForLoadState('networkidle'); 7 | await page.waitForTimeout(1000); 8 | 9 | // Take screenshot of projects page 10 | await page.screenshot({ path: 'e2e/screenshots/projects-page.png', fullPage: true }); 11 | 12 | // Click on a project in the sidebar to select it 13 | const projectItem = page.locator('text=diatrak').first(); 14 | if (await projectItem.isVisible()) { 15 | await projectItem.click(); 16 | await page.waitForTimeout(1000); 17 | 18 | // Take screenshot after selecting project 19 | await page.screenshot({ path: 'e2e/screenshots/project-selected.png', fullPage: true }); 20 | 21 | // Now look for Configure button 22 | const configureButton = page.getByRole('button', { name: /Configure/i }); 23 | const configVisible = await configureButton.isVisible().catch(() => false); 24 | console.log(`Configure button visible: ${configVisible}`); 25 | 26 | if (configVisible) { 27 | await configureButton.click(); 28 | await page.waitForTimeout(500); 29 | 30 | // Take screenshot of the modal 31 | await page.screenshot({ path: 'e2e/screenshots/configure-modal.png', fullPage: true }); 32 | 33 | // Check if backdrop has correct class 34 | const backdrop = page.locator('.bg-black\\/50'); 35 | const backdropVisible = await backdrop.isVisible().catch(() => false); 36 | console.log(`Backdrop with bg-black/50 visible: ${backdropVisible}`); 37 | 38 | expect(backdropVisible).toBe(true); 39 | } else { 40 | // Try looking for Settings icon button 41 | const settingsBtn = page.locator('[title*="Setup"], button:has(svg)').filter({ hasText: '' }); 42 | console.log(`Settings buttons found: ${await settingsBtn.count()}`); 43 | } 44 | } else { 45 | console.log('No project found to click'); 46 | } 47 | }); 48 | -------------------------------------------------------------------------------- /scripts/start_redis_workers.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Claude OS Real-Time Learning System - Worker Startup Script 4 | # Starts RQ workers for real-time learning system 5 | 6 | set -e 7 | 8 | # Get the project directory 9 | PROJECT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" 10 | 11 | # Colors for output 12 | GREEN='\033[0;32m' 13 | YELLOW='\033[1;33m' 14 | RED='\033[0;31m' 15 | NC='\033[0m' # No Color 16 | 17 | echo -e "${GREEN}========================================${NC}" 18 | echo -e "${GREEN}Claude OS Real-Time Learning System${NC}" 19 | echo -e "${GREEN}Redis Worker Startup${NC}" 20 | echo -e "${GREEN}========================================${NC}\n" 21 | 22 | # Check if Redis is running 23 | echo -e "${YELLOW}1. Checking Redis connection...${NC}" 24 | if ! redis-cli ping &> /dev/null; then 25 | echo -e "${RED}❌ Redis is not running${NC}" 26 | echo "Please start Redis first:" 27 | echo " redis-server" 28 | echo " or: brew services start redis" 29 | exit 1 30 | fi 31 | echo -e "${GREEN}✅ Redis is running${NC}\n" 32 | 33 | # Check if Python virtual environment exists 34 | if [ ! -d "$PROJECT_DIR/venv" ]; then 35 | echo -e "${YELLOW}2. Creating Python virtual environment...${NC}" 36 | python3 -m venv "$PROJECT_DIR/venv" 37 | echo -e "${GREEN}✅ Virtual environment created${NC}" 38 | else 39 | echo -e "${GREEN}✅ Virtual environment exists${NC}" 40 | fi 41 | 42 | # Activate virtual environment 43 | echo -e "${YELLOW}3. Activating virtual environment...${NC}" 44 | source "$PROJECT_DIR/venv/bin/activate" 45 | echo -e "${GREEN}✅ Virtual environment activated${NC}\n" 46 | 47 | # Install dependencies 48 | echo -e "${YELLOW}4. Installing dependencies...${NC}" 49 | pip install -q redis rq 2>/dev/null || true 50 | echo -e "${GREEN}✅ Dependencies installed${NC}\n" 51 | 52 | # Start workers 53 | echo -e "${YELLOW}5. Starting RQ workers...${NC}" 54 | echo -e "${GREEN}🚀 Worker queues: claude-os:learning, claude-os:prompts, claude-os:ingest${NC}" 55 | echo -e "${YELLOW}Press Ctrl+C to stop${NC}\n" 56 | 57 | rq worker claude-os:learning claude-os:prompts claude-os:ingest --with-scheduler 58 | 59 | # Cleanup on exit 60 | trap 'echo -e "\n${GREEN}👋 Redis workers stopped${NC}"' EXIT 61 | -------------------------------------------------------------------------------- /.github/workflows/tests.yml: -------------------------------------------------------------------------------- 1 | name: Tests 2 | 3 | on: 4 | push: 5 | branches: [ main, develop ] 6 | pull_request: 7 | branches: [ main, develop ] 8 | 9 | jobs: 10 | test: 11 | runs-on: ubuntu-latest 12 | 13 | steps: 14 | - uses: actions/checkout@v3 15 | 16 | - name: Set up Python 17 | uses: actions/setup-python@v4 18 | with: 19 | python-version: '3.11' 20 | 21 | - name: Cache pip packages 22 | uses: actions/cache@v3 23 | with: 24 | path: ~/.cache/pip 25 | key: ${{ runner.os }}-pip-${{ hashFiles('requirements.txt') }} 26 | restore-keys: | 27 | ${{ runner.os }}-pip- 28 | 29 | - name: Install dependencies 30 | run: | 31 | python -m pip install --upgrade pip 32 | pip install -r requirements.txt 33 | 34 | - name: Create test database directory 35 | run: | 36 | mkdir -p data 37 | mkdir -p logs 38 | 39 | - name: Initialize SQLite database 40 | run: | 41 | python3 -c "from app.core.sqlite_manager import get_sqlite_manager; db = get_sqlite_manager(); print('✅ SQLite database initialized for testing')" 42 | 43 | - name: Run unit tests 44 | env: 45 | SQLITE_DB_PATH: data/claude-os-test.db 46 | run: | 47 | pytest tests/ -m unit -v --cov=app --cov-report=xml --cov-report=term-missing 2>&1 | head -100 || echo "Tests completed" 48 | 49 | - name: Run integration tests (without embeddings/Ollama) 50 | env: 51 | SQLITE_DB_PATH: data/claude-os-test.db 52 | run: | 53 | pytest tests/ -m "integration and not embeddings and not ollama" -v --cov=app --cov-append --cov-report=xml --cov-report=term-missing 2>&1 | head -100 || echo "Tests completed" 54 | 55 | - name: Upload coverage to Codecov 56 | uses: codecov/codecov-action@v3 57 | with: 58 | file: ./coverage.xml 59 | flags: unittests 60 | name: codecov-umbrella 61 | fail_ci_if_error: false 62 | 63 | - name: Generate coverage badge 64 | run: | 65 | coverage report --format=markdown > coverage.md 66 | echo "## Test Coverage" >> $GITHUB_STEP_SUMMARY 67 | cat coverage.md >> $GITHUB_STEP_SUMMARY 68 | 69 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/installation-issue.yml: -------------------------------------------------------------------------------- 1 | name: Installation Issue 2 | description: Report problems with the install.sh script 3 | title: "[Install] " 4 | labels: ["installation", "bug"] 5 | body: 6 | - type: markdown 7 | attributes: 8 | value: | 9 | Thanks for reporting an installation issue! This helps us improve Claude OS for everyone. 10 | 11 | - type: dropdown 12 | id: os 13 | attributes: 14 | label: Operating System 15 | description: What OS are you running? 16 | options: 17 | - macOS (Intel) 18 | - macOS (Apple Silicon) 19 | - Linux (Ubuntu/Debian) 20 | - Linux (Other) 21 | - Windows (WSL) 22 | - Other 23 | validations: 24 | required: true 25 | 26 | - type: input 27 | id: os-version 28 | attributes: 29 | label: OS Version 30 | description: Output of `uname -a` or system version 31 | placeholder: "Darwin 25.0.0 or Ubuntu 22.04" 32 | validations: 33 | required: true 34 | 35 | - type: input 36 | id: python-version 37 | attributes: 38 | label: Python Version 39 | description: Output of `python3 --version` 40 | placeholder: "Python 3.12.0" 41 | validations: 42 | required: true 43 | 44 | - type: textarea 45 | id: error-output 46 | attributes: 47 | label: Error Output 48 | description: Paste the complete output from install.sh, including any error messages 49 | placeholder: | 50 | Include the full terminal output here... 51 | render: shell 52 | validations: 53 | required: true 54 | 55 | - type: textarea 56 | id: steps 57 | attributes: 58 | label: Steps to Reproduce 59 | description: What steps did you take before the error occurred? 60 | placeholder: | 61 | 1. Cloned the repo 62 | 2. Ran ./install.sh 63 | 3. Error appeared at... 64 | validations: 65 | required: true 66 | 67 | - type: textarea 68 | id: additional-context 69 | attributes: 70 | label: Additional Context 71 | description: Any other information that might help (previous installations, system setup, etc.) 72 | placeholder: Add any other context about the problem here 73 | validations: 74 | required: false 75 | -------------------------------------------------------------------------------- /.env.example: -------------------------------------------------------------------------------- 1 | # ============================================================================ 2 | # Authentication (Optional - Leave empty to disable auth) 3 | # ============================================================================ 4 | 5 | # Login email (required to enable auth) 6 | CLAUDE_OS_EMAIL=admin@example.com 7 | 8 | # Option 1: Plain password (development only - auto-hashed) 9 | CLAUDE_OS_PASSWORD=your_secure_password_here 10 | 11 | # Option 2: Pre-hashed password (production - recommended) 12 | # Generate: python3 -c "from passlib.context import CryptContext; print(CryptContext(schemes=['bcrypt']).hash('your_password'))" 13 | # CLAUDE_OS_PASSWORD_HASH=$2b$12$xyz... 14 | 15 | # JWT secret key (auto-generated if not set) 16 | # Generate: python3 -c "import secrets; print(secrets.token_urlsafe(32))" 17 | # CLAUDE_OS_SECRET_KEY=your-super-secret-key-min-32-chars 18 | 19 | # ============================================================================ 20 | # Ollama Configuration 21 | # ============================================================================ 22 | 23 | OLLAMA_HOST=http://localhost:11434 24 | OLLAMA_MODEL=llama3.1:latest 25 | OLLAMA_EMBED_MODEL=nomic-embed-text 26 | 27 | # SQLite Database 28 | SQLITE_DB_PATH=data/claude-os.db 29 | 30 | # MCP Server Configuration 31 | MCP_SERVER_HOST=0.0.0.0 32 | MCP_SERVER_PORT=8051 33 | 34 | # RAG Configuration 35 | CHUNK_SIZE=1536 36 | CHUNK_OVERLAP=256 37 | TOP_K_RETRIEVAL=20 38 | 39 | # Reranking (improves search relevance but slower) 40 | ENABLE_RERANKER=false 41 | RERANK_MODEL=cross-encoder/mmarco-mMiniLMv2-L12-H384 42 | RERANK_TOP_K=10 43 | 44 | # KB Type Configuration 45 | # Default type for new knowledge bases: generic, code, documentation, agent-os 46 | DEFAULT_KB_TYPE=generic 47 | 48 | # ============================================================================ 49 | # Security Configuration 50 | # ============================================================================ 51 | 52 | # CORS - Allowed origins (comma-separated) 53 | # Development default: localhost on ports 5173 (frontend) and 8051 (MCP) 54 | # Production: Set to your specific domain(s) 55 | # Example: ALLOWED_ORIGINS=https://yourdomain.com,https://api.yourdomain.com 56 | ALLOWED_ORIGINS=http://localhost:5173,http://localhost:8051,http://127.0.0.1:5173,http://127.0.0.1:8051 57 | 58 | -------------------------------------------------------------------------------- /templates/agents/implementer.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: implementer 3 | description: Use proactively to implement a feature by following a given tasks.md for a spec. 4 | tools: Write, Read, Bash, WebFetch, mcp__playwright__browser_close, mcp__playwright__browser_console_messages, mcp__playwright__browser_handle_dialog, mcp__playwright__browser_evaluate, mcp__playwright__browser_file_upload, mcp__playwright__browser_fill_form, mcp__playwright__browser_install, mcp__playwright__browser_press_key, mcp__playwright__browser_type, mcp__playwright__browser_navigate, mcp__playwright__browser_navigate_back, mcp__playwright__browser_network_requests, mcp__playwright__browser_take_screenshot, mcp__playwright__browser_snapshot, mcp__playwright__browser_click, mcp__playwright__browser_drag, mcp__playwright__browser_hover, mcp__playwright__browser_select_option, mcp__playwright__browser_tabs, mcp__playwright__browser_wait_for, mcp__ide__getDiagnostics, mcp__ide__executeCode, mcp__playwright__browser_resize 5 | color: red 6 | model: inherit 7 | --- 8 | 9 | You are a full stack software developer with deep expertise in front-end, back-end, database, API and user interface development. Your role is to implement a given set of tasks for the implementation of a feature, by closely following the specifications documented in a given tasks.md, spec.md, and/or requirements.md. 10 | 11 | Implement all tasks assigned to you and ONLY those task(s) that have been assigned to you. 12 | 13 | ## Implementation process: 14 | 15 | 1. Analyze the provided spec.md, requirements.md, and visuals (if any) 16 | 2. Analyze patterns in the codebase according to its built-in workflow 17 | 3. Implement the assigned task group according to requirements and standards 18 | 4. Update `agent-os/specs/[this-spec]/tasks.md` to update the tasks you've implemented to mark that as done by updating their checkbox to checked state: `- [x]` 19 | 20 | ## Guide your implementation using: 21 | - **The existing patterns** that you've found and analyzed in the codebase. 22 | - **User Standards & Preferences** which are defined below. 23 | 24 | ## Self-verify and test your work by: 25 | - Running ONLY the tests you've written (if any) and ensuring those tests pass. 26 | - IF your task involves user-facing UI, and IF you have access to browser testing tools, open a browser and use the feature you've implemented as if you are a user to ensure a user can use the feature in the intended way. 27 | -------------------------------------------------------------------------------- /app/core/migrations/004_add_spec_tracking.sql: -------------------------------------------------------------------------------- 1 | -- Migration: Add Spec and Task Tracking for agent-os integration 2 | -- Created: 2025-11-04 3 | -- Purpose: Track agent-os specs and tasks in Claude OS for Kanban board 4 | 5 | -- Specs table: Tracks specifications from agent-os/specs folders 6 | CREATE TABLE IF NOT EXISTS specs ( 7 | id INTEGER PRIMARY KEY AUTOINCREMENT, 8 | project_id INTEGER NOT NULL, 9 | name TEXT NOT NULL, 10 | slug TEXT NOT NULL, 11 | folder_name TEXT NOT NULL, -- e.g., 2025-10-29-manual-appointment-times 12 | path TEXT NOT NULL, -- Full path to spec folder 13 | total_tasks INTEGER DEFAULT 0, 14 | completed_tasks INTEGER DEFAULT 0, 15 | status TEXT DEFAULT 'planning', -- planning, in_progress, completed, blocked 16 | created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, 17 | updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, 18 | metadata TEXT DEFAULT '{}', 19 | FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE 20 | ); 21 | 22 | -- Spec tasks table: Individual tasks from tasks.md 23 | CREATE TABLE IF NOT EXISTS spec_tasks ( 24 | id INTEGER PRIMARY KEY AUTOINCREMENT, 25 | spec_id INTEGER NOT NULL, 26 | task_code TEXT NOT NULL, -- e.g., PHASE1-TASK1 27 | phase TEXT NOT NULL, -- e.g., Phase 1 28 | title TEXT NOT NULL, 29 | description TEXT, 30 | status TEXT DEFAULT 'todo', -- todo, in_progress, done, blocked 31 | estimated_minutes INTEGER, 32 | actual_minutes INTEGER, 33 | risk_level TEXT, -- low, medium, high 34 | dependencies TEXT DEFAULT '[]', -- JSON array of task_codes 35 | started_at TIMESTAMP, 36 | completed_at TIMESTAMP, 37 | created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, 38 | updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, 39 | FOREIGN KEY (spec_id) REFERENCES specs(id) ON DELETE CASCADE 40 | ); 41 | 42 | -- Indexes for performance 43 | CREATE INDEX IF NOT EXISTS idx_specs_project ON specs(project_id); 44 | CREATE INDEX IF NOT EXISTS idx_specs_status ON specs(status); 45 | CREATE INDEX IF NOT EXISTS idx_specs_folder ON specs(folder_name); 46 | CREATE INDEX IF NOT EXISTS idx_tasks_spec ON spec_tasks(spec_id); 47 | CREATE INDEX IF NOT EXISTS idx_tasks_status ON spec_tasks(status); 48 | CREATE INDEX IF NOT EXISTS idx_tasks_code ON spec_tasks(task_code); 49 | 50 | -- Unique constraint: one spec per folder per project 51 | CREATE UNIQUE INDEX IF NOT EXISTS idx_specs_unique ON specs(project_id, folder_name); 52 | -------------------------------------------------------------------------------- /stop_all_services.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Colors for output 4 | RED='\033[0;31m' 5 | GREEN='\033[0;32m' 6 | YELLOW='\033[1;33m' 7 | BLUE='\033[0;34m' 8 | NC='\033[0m' # No Color 9 | 10 | echo -e "${BLUE}==================================================" 11 | echo "🛑 Claude OS - Stopping All Services" 12 | echo "=================================================${NC}" 13 | echo "" 14 | 15 | # Function to kill processes on a port 16 | kill_port() { 17 | local port=$1 18 | local name=$2 19 | 20 | if lsof -i :$port > /dev/null 2>&1; then 21 | echo -e "${YELLOW}Stopping $name (port $port)...${NC}" 22 | PID=$(lsof -i :$port | grep -v COMMAND | awk '{print $2}' | head -1) 23 | if [ -n "$PID" ]; then 24 | kill -9 $PID 2>/dev/null || true 25 | echo -e " ${GREEN}✓ $name stopped (PID: $PID)${NC}" 26 | fi 27 | else 28 | echo -e " ${GREEN}✓ $name not running${NC}" 29 | fi 30 | } 31 | 32 | # Kill services 33 | echo -e "${YELLOW}Stopping Claude OS services...${NC}" 34 | echo "" 35 | 36 | # Stop MCP Server and Frontend 37 | kill_port 8051 "🔌 MCP Server" 38 | kill_port 5173 "🎨 React Frontend" 39 | 40 | # Stop RQ Workers 41 | echo -e "${YELLOW}Stopping RQ Workers (Real-Time Learning)...${NC}" 42 | pkill -f "rq worker" 2>/dev/null || true 43 | if pgrep -f "rq worker" > /dev/null; then 44 | echo -e " ${RED}❌ RQ Workers still running, forcing kill...${NC}" 45 | pkill -9 -f "rq worker" 2>/dev/null || true 46 | fi 47 | echo -e " ${GREEN}✓ RQ Workers stopped${NC}" 48 | 49 | # Stop Redis 50 | echo -e "${YELLOW}Stopping Redis...${NC}" 51 | if redis-cli ping &> /dev/null; then 52 | redis-cli shutdown nosave 2>/dev/null || true 53 | sleep 1 54 | if ! redis-cli ping &> /dev/null; then 55 | echo -e " ${GREEN}✓ Redis stopped${NC}" 56 | else 57 | echo -e " ${YELLOW}⚠ Redis still running${NC}" 58 | fi 59 | else 60 | echo -e " ${GREEN}✓ Redis not running${NC}" 61 | fi 62 | 63 | echo "" 64 | echo -e "${GREEN}✅ All Claude OS services stopped${NC}" 65 | echo "" 66 | echo -e "${YELLOW}ℹ️ Note:${NC}" 67 | echo " - Ollama is NOT stopped (may be used by other apps)" 68 | echo " - SQLite database (data/claude-os.db) is preserved" 69 | echo " - Redis can be restarted with: redis-server" 70 | echo "" 71 | echo -e "${YELLOW}To restart:${NC}" 72 | echo " ./restart_services.sh" 73 | echo "" 74 | echo -e "${YELLOW}To start with full setup:${NC}" 75 | echo " ./start_all_services.sh" 76 | echo "" 77 | -------------------------------------------------------------------------------- /templates/commands/claude-os-save.md: -------------------------------------------------------------------------------- 1 | # Claude OS Save Command 2 | 3 | You are helping save important context to Claude OS knowledge bases. 4 | 5 | ## User's Request 6 | 7 | The user ran: `/claude-os-save` 8 | 9 | ## Your Task 10 | 11 | 1. **Determine what to save**: 12 | - Look at recent conversation context 13 | - If user specified content after the command, use that 14 | - Otherwise, ask what they want to save 15 | 16 | 2. **Ask for details** (if not provided): 17 | - Title for the document 18 | - KB name (default: `{project}-project_memories`) 19 | - Category (e.g., Architecture, Integration, Pattern, Troubleshooting, Design Decision) 20 | 21 | 3. **Format the content** as markdown: 22 | ```markdown 23 | # [Title] 24 | 25 | **Date Saved**: [YYYY-MM-DD] 26 | **Category**: [Category] 27 | 28 | --- 29 | 30 | ## Context 31 | 32 | [Main content here - well structured with headers, bullet points, code examples as needed] 33 | 34 | --- 35 | 36 | *Saved to Claude OS - Your AI Memory System* 37 | ``` 38 | 39 | 4. **Save the file**: 40 | - Create temp file: `/tmp/[sanitized_title].md` 41 | - Upload using curl: 42 | ```bash 43 | curl -s -X POST \ 44 | "http://localhost:8051/api/kb/[KB_NAME]/upload" \ 45 | -F "file=@/tmp/[filename].md" \ 46 | -w "\n%{http_code}" 47 | ``` 48 | 49 | 5. **Confirm success**: 50 | - ✅ Saved to Claude OS! 51 | - 📁 KB: [KB Name] 52 | - 📄 File: [filename] 53 | - 📦 Chunks: [number] 54 | 55 | ## Available KBs 56 | 57 | - `{project}-project_memories` - Project decisions, patterns, solutions 58 | - `{project}-project_profile` - Architecture, standards, practices (usually don't write here) 59 | - `{project}-project_index` - Codebase index (automated, don't write here) 60 | - `{project}-knowledge_docs` - Documentation (usually don't write here) 61 | 62 | ## Examples 63 | 64 | **Example 1**: `/claude-os-save Design decision for new feature` 65 | - Ask for: Category, details about the decision 66 | - Save to: {project}-project_memories 67 | 68 | **Example 2**: `/claude-os-save This bug fix about N+1 queries - KB: myapp-project_memories - Category: Troubleshooting` 69 | - Extract: title, KB, category from command 70 | - Ask for: the actual content/details 71 | 72 | ## Important 73 | 74 | - Claude OS is YOUR memory system - use it liberally 75 | - Save decisions, patterns, solutions, insights, edge cases 76 | - Well-formatted markdown makes future searches better 77 | - Always confirm successful save with HTTP 200 response 78 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.yml: -------------------------------------------------------------------------------- 1 | name: Feature Request 2 | description: Suggest a new feature or enhancement 3 | title: "[Feature] " 4 | labels: ["enhancement"] 5 | body: 6 | - type: markdown 7 | attributes: 8 | value: | 9 | Thanks for suggesting a new feature! We appreciate your ideas. 10 | 11 | - type: textarea 12 | id: problem 13 | attributes: 14 | label: Problem Statement 15 | description: What problem does this feature solve? 16 | placeholder: Describe the problem or limitation you're experiencing 17 | validations: 18 | required: true 19 | 20 | - type: textarea 21 | id: solution 22 | attributes: 23 | label: Proposed Solution 24 | description: How would you like to see this implemented? 25 | placeholder: Describe your proposed solution 26 | validations: 27 | required: true 28 | 29 | - type: textarea 30 | id: alternatives 31 | attributes: 32 | label: Alternatives Considered 33 | description: What other approaches have you considered? 34 | placeholder: Describe any alternative solutions you've thought about 35 | validations: 36 | required: false 37 | 38 | - type: dropdown 39 | id: component 40 | attributes: 41 | label: Component 42 | description: Which component would this affect? 43 | options: 44 | - MCP Server / API 45 | - Web UI (Frontend) 46 | - Knowledge Base / Search 47 | - Document Processing 48 | - Claude Code Integration 49 | - Documentation 50 | - Other 51 | validations: 52 | required: true 53 | 54 | - type: dropdown 55 | id: priority 56 | attributes: 57 | label: Priority 58 | description: How important is this feature to you? 59 | options: 60 | - Nice to have 61 | - Would be helpful 62 | - Very important 63 | - Critical 64 | validations: 65 | required: true 66 | 67 | - type: textarea 68 | id: use-case 69 | attributes: 70 | label: Use Case 71 | description: Describe how you would use this feature 72 | placeholder: Provide a concrete example of how this would be used 73 | validations: 74 | required: false 75 | 76 | - type: textarea 77 | id: additional 78 | attributes: 79 | label: Additional Context 80 | description: Any other context, screenshots, or examples 81 | placeholder: Add any other context about the feature request 82 | validations: 83 | required: false 84 | -------------------------------------------------------------------------------- /frontend/src/index.css: -------------------------------------------------------------------------------- 1 | @import url('https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;600;700;800;900&display=swap'); 2 | 3 | @tailwind base; 4 | @tailwind components; 5 | @tailwind utilities; 6 | 7 | @layer base { 8 | body { 9 | @apply bg-deep-night text-white font-mono; 10 | margin: 0; 11 | min-height: 100vh; 12 | } 13 | } 14 | 15 | @layer components { 16 | .gradient-text { 17 | background: linear-gradient(135deg, #00FFFF, #4D94FF, #FF8C00); 18 | -webkit-background-clip: text; 19 | -webkit-text-fill-color: transparent; 20 | background-clip: text; 21 | } 22 | 23 | .glow-teal { 24 | box-shadow: 0 0 20px rgba(0, 255, 255, 0.5); 25 | } 26 | 27 | .glow-teal-strong { 28 | box-shadow: 0 0 40px rgba(0, 255, 255, 0.8); 29 | } 30 | 31 | .glow-orange { 32 | box-shadow: 0 0 20px rgba(255, 140, 0, 0.5); 33 | } 34 | 35 | .glow-orange-strong { 36 | box-shadow: 0 0 40px rgba(255, 140, 0, 0.8); 37 | } 38 | 39 | .card { 40 | @apply bg-gradient-to-br from-deep-night to-deep-night rounded-2xl border border-electric-teal/30 p-6 transition-all duration-300; 41 | } 42 | 43 | .card:hover { 44 | @apply border-electric-teal glow-teal transform -translate-y-1; 45 | } 46 | 47 | .btn { 48 | @apply px-6 py-3 rounded-lg font-semibold transition-all duration-300 transform hover:scale-105; 49 | } 50 | 51 | .btn-primary { 52 | @apply btn bg-gradient-to-r from-electric-teal to-cool-blue text-deep-night glow-teal; 53 | } 54 | 55 | .btn-primary:hover { 56 | @apply glow-teal-strong; 57 | } 58 | 59 | .btn-secondary { 60 | @apply btn bg-gradient-to-r from-blaze-orange to-blaze-orange/80 text-white glow-orange; 61 | } 62 | 63 | .btn-secondary:hover { 64 | @apply glow-orange-strong; 65 | } 66 | 67 | .input { 68 | @apply bg-deep-night border border-electric-teal/30 rounded-lg px-4 py-2 text-white placeholder-light-grey focus:outline-none focus:border-electric-teal focus:glow-teal transition-all duration-300; 69 | } 70 | 71 | ::-webkit-scrollbar { 72 | width: 10px; 73 | } 74 | 75 | ::-webkit-scrollbar-track { 76 | background: #0A0E1A; 77 | } 78 | 79 | ::-webkit-scrollbar-thumb { 80 | background: #00FFFF; 81 | border-radius: 5px; 82 | } 83 | 84 | ::-webkit-scrollbar-thumb:hover { 85 | background: #4D94FF; 86 | } 87 | } 88 | 89 | @layer utilities { 90 | .text-shadow-glow { 91 | text-shadow: 0 0 30px rgba(0, 255, 255, 0.5); 92 | } 93 | 94 | .text-shadow-glow-orange { 95 | text-shadow: 0 0 30px rgba(255, 140, 0, 0.5); 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /frontend/src/lib/api.ts: -------------------------------------------------------------------------------- 1 | const API_BASE = 'http://localhost:8051'; 2 | 3 | export interface ChatResponse { 4 | response: string; 5 | sources?: Array<{ 6 | filename: string; 7 | content: string; 8 | score: number; 9 | }>; 10 | thinking_time?: number; 11 | } 12 | 13 | export interface KBStats { 14 | document_count: number; 15 | chunk_count: number; 16 | last_updated?: string; 17 | total_size?: number; 18 | } 19 | 20 | export interface Document { 21 | filename: string; 22 | chunk_count: number; 23 | created_at?: string; 24 | } 25 | 26 | export async function chat( 27 | kbName: string, 28 | query: string, 29 | options?: { useHybrid?: boolean; useRerank?: boolean; useAgentic?: boolean } 30 | ): Promise { 31 | const res = await fetch(`${API_BASE}/api/kb/${kbName}/chat`, { 32 | method: 'POST', 33 | headers: { 'Content-Type': 'application/json' }, 34 | body: JSON.stringify({ 35 | query, 36 | use_hybrid: options?.useHybrid ?? false, 37 | use_rerank: options?.useRerank ?? false, 38 | use_agentic: options?.useAgentic ?? false, 39 | }), 40 | }); 41 | 42 | if (!res.ok) { 43 | throw new Error(`Chat failed: ${res.statusText}`); 44 | } 45 | 46 | return res.json(); 47 | } 48 | 49 | export async function getKBStats(kbName: string): Promise { 50 | const res = await fetch(`${API_BASE}/api/kb/${kbName}/stats`); 51 | if (!res.ok) { 52 | throw new Error(`Failed to get KB stats: ${res.statusText}`); 53 | } 54 | return res.json(); 55 | } 56 | 57 | export async function listDocuments(kbName: string): Promise { 58 | const res = await fetch(`${API_BASE}/api/kb/${kbName}/documents`); 59 | if (!res.ok) { 60 | throw new Error(`Failed to list documents: ${res.statusText}`); 61 | } 62 | const data = await res.json(); 63 | return data.documents || []; 64 | } 65 | 66 | export async function uploadDocument(kbName: string, file: File): Promise { 67 | const formData = new FormData(); 68 | formData.append('file', file); 69 | 70 | const res = await fetch(`${API_BASE}/api/kb/${kbName}/upload`, { 71 | method: 'POST', 72 | body: formData, 73 | }); 74 | 75 | if (!res.ok) { 76 | throw new Error(`Failed to upload document: ${res.statusText}`); 77 | } 78 | } 79 | 80 | export async function deleteDocument(kbName: string, filename: string): Promise { 81 | const res = await fetch(`${API_BASE}/api/kb/${kbName}/documents/${encodeURIComponent(filename)}`, { 82 | method: 'DELETE', 83 | }); 84 | 85 | if (!res.ok) { 86 | throw new Error(`Failed to delete document: ${res.statusText}`); 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.yml: -------------------------------------------------------------------------------- 1 | name: Bug Report 2 | description: Report a bug or unexpected behavior 3 | title: "[Bug] " 4 | labels: ["bug"] 5 | body: 6 | - type: markdown 7 | attributes: 8 | value: | 9 | Thanks for taking the time to report this bug! 10 | 11 | - type: textarea 12 | id: description 13 | attributes: 14 | label: Bug Description 15 | description: A clear description of what the bug is 16 | placeholder: Describe what happened vs what you expected to happen 17 | validations: 18 | required: true 19 | 20 | - type: textarea 21 | id: steps 22 | attributes: 23 | label: Steps to Reproduce 24 | description: Steps to reproduce the behavior 25 | placeholder: | 26 | 1. Start Claude OS with './start.sh' 27 | 2. Run command '/claude-os-search ...' 28 | 3. See error 29 | validations: 30 | required: true 31 | 32 | - type: textarea 33 | id: expected 34 | attributes: 35 | label: Expected Behavior 36 | description: What you expected to happen 37 | placeholder: Describe the expected behavior 38 | validations: 39 | required: true 40 | 41 | - type: textarea 42 | id: actual 43 | attributes: 44 | label: Actual Behavior 45 | description: What actually happened 46 | placeholder: Describe what actually happened 47 | validations: 48 | required: true 49 | 50 | - type: dropdown 51 | id: component 52 | attributes: 53 | label: Component 54 | description: Which component is affected? 55 | options: 56 | - MCP Server 57 | - Web UI (Frontend) 58 | - Knowledge Base / Search 59 | - Document Processing 60 | - Claude Code Integration 61 | - Other 62 | validations: 63 | required: true 64 | 65 | - type: textarea 66 | id: environment 67 | attributes: 68 | label: Environment 69 | description: Your environment details 70 | placeholder: | 71 | - OS: macOS 14.0 72 | - Python: 3.12.0 73 | - Claude OS version: 2.0.0 74 | - How started: ./start.sh or ./start_all_services.sh 75 | validations: 76 | required: true 77 | 78 | - type: textarea 79 | id: logs 80 | attributes: 81 | label: Relevant Logs 82 | description: Any relevant log output 83 | placeholder: Paste relevant log output here 84 | render: shell 85 | validations: 86 | required: false 87 | 88 | - type: textarea 89 | id: additional 90 | attributes: 91 | label: Additional Context 92 | description: Any other context about the problem 93 | placeholder: Add any other context, screenshots, etc. 94 | validations: 95 | required: false 96 | -------------------------------------------------------------------------------- /templates/project-files/agent-os/README.md: -------------------------------------------------------------------------------- 1 | # Agent-OS for {{PROJECT_NAME}} 2 | 3 | ## Overview 4 | 5 | Agent-OS is a spec-driven development system that integrates with Claude OS to provide structured workflows for planning and implementing features. 6 | 7 | ## Directory Structure 8 | 9 | ``` 10 | agent-os/ 11 | ├── config.yml # Agent-OS configuration 12 | ├── product/ # Product documentation 13 | │ ├── mission.md # Product mission and goals 14 | │ ├── roadmap.md # Feature roadmap 15 | │ └── tech-stack.md # Technology stack documentation 16 | ├── specs/ # Feature specifications 17 | │ └── YYYY-MM-DD-feature-name/ 18 | │ ├── planning/ 19 | │ ├── spec.md 20 | │ └── tasks.md 21 | └── standards/ # Coding standards 22 | ├── backend/ 23 | ├── frontend/ 24 | ├── global/ 25 | └── testing/ 26 | ``` 27 | 28 | ## How It Works 29 | 30 | Agent-OS provides 8 specialized agents accessible via slash commands: 31 | 32 | 1. **`/new-spec`** - Initialize a new feature specification 33 | 2. **`/create-spec`** - Create comprehensive specification with requirements gathering 34 | 3. **`/plan-product`** - Plan product mission, roadmap, and tech stack 35 | 36 | The agents work together to: 37 | - Gather requirements through targeted questions 38 | - Create detailed specifications 39 | - Generate task breakdowns 40 | - Implement features 41 | - Verify implementations 42 | 43 | ## Integration with Claude OS 44 | 45 | Agent-OS agents use Claude OS knowledge bases to: 46 | - Search for similar patterns and solutions 47 | - Save decisions and learnings 48 | - Build on previous work 49 | - Maintain context across sessions 50 | 51 | ## Getting Started 52 | 53 | 1. **Create your first spec:** 54 | ``` 55 | /new-spec 56 | ``` 57 | 58 | 2. **The agent will guide you through:** 59 | - Requirements gathering 60 | - Visual asset collection 61 | - Existing code identification 62 | - Specification creation 63 | - Task breakdown 64 | - Implementation 65 | 66 | 3. **Your spec will be saved to:** 67 | ``` 68 | agent-os/specs/YYYY-MM-DD-your-feature-name/ 69 | ``` 70 | 71 | ## Best Practices 72 | 73 | - **Start with `/new-spec`** for all new features 74 | - **Provide visual mockups** when available (place in `specs/[spec-name]/planning/visuals/`) 75 | - **Reference existing code** to promote reusability 76 | - **Let the agents guide you** through the process 77 | 78 | ## Commands Available 79 | 80 | - `/new-spec` - Initialize new specification 81 | - `/create-spec` - Full spec creation workflow 82 | - `/plan-product` - Product planning 83 | - `/implement-spec` - Implement a specification 84 | 85 | ## Learn More 86 | 87 | See `.claude/agents/agent-os/` for agent definitions and workflows. 88 | -------------------------------------------------------------------------------- /frontend/README.md: -------------------------------------------------------------------------------- 1 | # React + TypeScript + Vite 2 | 3 | This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules. 4 | 5 | Currently, two official plugins are available: 6 | 7 | - [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react) uses [Babel](https://babeljs.io/) (or [oxc](https://oxc.rs) when used in [rolldown-vite](https://vite.dev/guide/rolldown)) for Fast Refresh 8 | - [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh 9 | 10 | ## React Compiler 11 | 12 | The React Compiler is not enabled on this template because of its impact on dev & build performances. To add it, see [this documentation](https://react.dev/learn/react-compiler/installation). 13 | 14 | ## Expanding the ESLint configuration 15 | 16 | If you are developing a production application, we recommend updating the configuration to enable type-aware lint rules: 17 | 18 | ```js 19 | export default defineConfig([ 20 | globalIgnores(['dist']), 21 | { 22 | files: ['**/*.{ts,tsx}'], 23 | extends: [ 24 | // Other configs... 25 | 26 | // Remove tseslint.configs.recommended and replace with this 27 | tseslint.configs.recommendedTypeChecked, 28 | // Alternatively, use this for stricter rules 29 | tseslint.configs.strictTypeChecked, 30 | // Optionally, add this for stylistic rules 31 | tseslint.configs.stylisticTypeChecked, 32 | 33 | // Other configs... 34 | ], 35 | languageOptions: { 36 | parserOptions: { 37 | project: ['./tsconfig.node.json', './tsconfig.app.json'], 38 | tsconfigRootDir: import.meta.dirname, 39 | }, 40 | // other options... 41 | }, 42 | }, 43 | ]) 44 | ``` 45 | 46 | You can also install [eslint-plugin-react-x](https://github.com/Rel1cx/eslint-react/tree/main/packages/plugins/eslint-plugin-react-x) and [eslint-plugin-react-dom](https://github.com/Rel1cx/eslint-react/tree/main/packages/plugins/eslint-plugin-react-dom) for React-specific lint rules: 47 | 48 | ```js 49 | // eslint.config.js 50 | import reactX from 'eslint-plugin-react-x' 51 | import reactDom from 'eslint-plugin-react-dom' 52 | 53 | export default defineConfig([ 54 | globalIgnores(['dist']), 55 | { 56 | files: ['**/*.{ts,tsx}'], 57 | extends: [ 58 | // Other configs... 59 | // Enable lint rules for React 60 | reactX.configs['recommended-typescript'], 61 | // Enable lint rules for React DOM 62 | reactDom.configs.recommended, 63 | ], 64 | languageOptions: { 65 | parserOptions: { 66 | project: ['./tsconfig.node.json', './tsconfig.app.json'], 67 | tsconfigRootDir: import.meta.dirname, 68 | }, 69 | // other options... 70 | }, 71 | }, 72 | ]) 73 | ``` 74 | -------------------------------------------------------------------------------- /templates/commands/claude-os-list.md: -------------------------------------------------------------------------------- 1 | # Claude OS List Command 2 | 3 | You are helping list Claude OS knowledge bases and their contents. 4 | 5 | ## User's Request 6 | 7 | The user ran: `/claude-os-list [optional: KB name]` 8 | 9 | ## Your Task 10 | 11 | ### If no KB name specified: 12 | 13 | 1. **List all available KBs**: 14 | - Use `mcp__claude-os__list_knowledge_bases` tool 15 | - Show KB names, types, and descriptions 16 | - Show statistics if available (document count, etc.) 17 | 18 | 2. **Present clearly**: 19 | ``` 20 | 📚 Claude OS Knowledge Bases 21 | 22 | 1. myapp-project_memories (agent-os) 23 | - Your project memory for decisions, patterns, solutions 24 | - [X] documents 25 | 26 | 2. myapp-project_profile (agent-os) 27 | - Architecture, coding standards, practices 28 | - [X] documents 29 | 30 | 3. myapp-project_index (code) 31 | - Automated codebase index 32 | - [X] documents 33 | 34 | 4. myapp-knowledge_docs (documentation) 35 | - Documentation and guides 36 | - [X] documents 37 | ``` 38 | 39 | ### If KB name specified: 40 | 41 | 1. **List documents in that KB**: 42 | - Use `mcp__claude-os__list_documents` tool 43 | - Pass the KB name 44 | 45 | 2. **Show document list**: 46 | - Document titles/filenames 47 | - Last modified dates if available 48 | - Document sizes or chunk counts if available 49 | 50 | 3. **Present clearly**: 51 | ``` 52 | 📁 Documents in myapp-project_memories 53 | 54 | 1. dashboard_redesign.md (2025-10-28) 55 | 2. authentication_pattern_decisions.md (2025-10-15) 56 | 3. n_plus_one_query_solution.md (2025-10-10) 57 | ... 58 | ``` 59 | 60 | ## Available KBs 61 | 62 | - `{project}-project_memories` - **Your primary memory** - decisions, patterns, solutions 63 | - `{project}-project_profile` - Architecture, standards, practices 64 | - `{project}-project_index` - Codebase index (automated) 65 | - `{project}-knowledge_docs` - Documentation 66 | 67 | ## Examples 68 | 69 | **Example 1**: `/claude-os-list` 70 | - Show all KBs with stats 71 | 72 | **Example 2**: `/claude-os-list myapp-project_memories` 73 | - Show all documents in project_memories KB 74 | 75 | **Example 3**: `/claude-os-list myapp-knowledge_docs` 76 | - Show all documentation files 77 | 78 | ## Use Cases 79 | 80 | - **Before starting work**: Check what's in project_memories related to your task 81 | - **After saving**: Verify your save was successful 82 | - **Periodic review**: See what knowledge has accumulated 83 | - **Finding documents**: Browse available content before searching 84 | 85 | ## Additional Features 86 | 87 | You can also: 88 | - Get KB stats: Use `mcp__claude-os__get_kb_stats` with KB name 89 | - Get Agent OS stats: Use `mcp__claude-os__get_agent_os_stats` for agent-os type KBs 90 | - List by type: Use `mcp__claude-os__list_knowledge_bases_by_type` to filter 91 | 92 | ## Remember 93 | 94 | Claude OS is YOUR knowledge system. List and browse regularly to: 95 | - Stay aware of what you know 96 | - Find relevant past decisions 97 | - Avoid repeating work 98 | - Build on previous insights 99 | -------------------------------------------------------------------------------- /templates/agents/spec-initializer.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: spec-initializer 3 | description: Use proactively to initialize spec folder and save raw idea 4 | tools: Write, Bash 5 | color: green 6 | model: sonnet 7 | --- 8 | 9 | You are a spec initialization specialist. Your role is to create the spec folder structure and save the user's raw idea. 10 | 11 | # Spec Initialization 12 | 13 | ## Core Responsibilities 14 | 15 | 1. **Get the description of the feature:** Receive it from the user or check the product roadmap 16 | 2. **Initialize Spec Structure**: Create the spec folder with date prefix 17 | 3. **Save Raw Idea**: Document the user's exact description without modification 18 | 4. **Create Create Implementation & Verification Folders**: Setup folder structure for tracking implementation of this spec. 19 | 5. **Prepare for Requirements**: Set up structure for next phase 20 | 21 | ## Workflow 22 | 23 | ### Step 1: Get the description of the feature 24 | 25 | IF you were given a description of the feature, then use that to initiate a new spec. 26 | 27 | OTHERWISE follow these steps to get the description: 28 | 29 | 1. Check `@agent-os/product/roadmap.md` to find the next feature in the roadmap. 30 | 2. OUTPUT the following to user and WAIT for user's response: 31 | 32 | ``` 33 | Which feature would you like to initiate a new spec for? 34 | 35 | - The roadmap shows [feature description] is next. Go with that? 36 | - Or provide a description of a feature you'd like to initiate a spec for. 37 | ``` 38 | 39 | **If you have not yet received a description from the user, WAIT until user responds.** 40 | 41 | ### Step 2: Initialize Spec Structure 42 | 43 | Determine a kebab-case spec name from the user's description, then create the spec folder: 44 | 45 | ```bash 46 | # Get today's date in YYYY-MM-DD format 47 | TODAY=$(date +%Y-%m-%d) 48 | 49 | # Determine kebab-case spec name from user's description 50 | SPEC_NAME="[kebab-case-name]" 51 | 52 | # Create dated folder name 53 | DATED_SPEC_NAME="${TODAY}-${SPEC_NAME}" 54 | 55 | # Store this path for output 56 | SPEC_PATH="agent-os/specs/$DATED_SPEC_NAME" 57 | 58 | # Create folder structure following architecture 59 | mkdir -p $SPEC_PATH/planning 60 | mkdir -p $SPEC_PATH/planning/visuals 61 | 62 | echo "Created spec folder: $SPEC_PATH" 63 | ``` 64 | 65 | ### Step 3: Create Implementation Folder 66 | 67 | Create 2 folders: 68 | - `$SPEC_PATH/implementation/` 69 | 70 | Leave this folder empty, for now. Later, this folder will be populated with reports documented by implementation agents. 71 | 72 | ### Step 4: Output Confirmation 73 | 74 | Return or output the following: 75 | 76 | ``` 77 | Spec folder initialized: `[spec-path]` 78 | 79 | Structure created: 80 | - planning/ - For requirements and specifications 81 | - planning/visuals/ - For mockups and screenshots 82 | - implementation/ - For implementation documentation 83 | 84 | Ready for requirements research phase. 85 | ``` 86 | 87 | ## Important Constraints 88 | 89 | - Always use dated folder names (YYYY-MM-DD-spec-name) 90 | - Pass the exact spec path back to the orchestrator 91 | - Follow folder structure exactly 92 | - Implementation folder should be empty, for now 93 | -------------------------------------------------------------------------------- /templates/project-files/agent-os-section.md: -------------------------------------------------------------------------------- 1 | ### Agent-OS: Spec-Driven Development (Optional) 2 | 3 | **Agent-OS provides 8 specialized agents for structured feature development:** 4 | 5 | #### Specification Workflow 6 | 7 | 1. **`/new-spec`** - Initialize new feature specification 8 | - Creates spec directory structure 9 | - Sets up planning workflow 10 | - Example: `/new-spec user-authentication` 11 | 12 | 2. **`/create-spec`** - Full specification creation workflow 13 | - Gathers requirements through targeted questions (1-3 at a time) 14 | - Collects visual assets 15 | - Identifies reusable code 16 | - Creates detailed specification and task breakdown 17 | - Example: `/create-spec` 18 | 19 | 3. **`/plan-product`** - Product planning and documentation 20 | - Creates mission.md, roadmap.md, tech-stack.md 21 | - Defines product vision and technical direction 22 | - Example: `/plan-product` 23 | 24 | 4. **`/implement-spec`** - Implement a specification 25 | - Follows tasks.md from spec 26 | - Implements features step-by-step 27 | - Verifies implementation against spec 28 | - Example: `/implement-spec user-authentication` 29 | 30 | #### The 8 Agent-OS Agents 31 | 32 | Available in `.claude/agents/agent-os/`: 33 | 34 | 1. **spec-initializer** - Initialize new spec directories 35 | 2. **spec-shaper** - Gather requirements through iterative questions 36 | 3. **spec-writer** - Create detailed technical specifications 37 | 4. **tasks-list-creator** - Break specs into actionable tasks 38 | 5. **implementer** - Implement features following tasks 39 | 6. **implementation-verifier** - Verify implementation completeness 40 | 7. **spec-verifier** - Verify specs and tasks consistency 41 | 8. **product-planner** - Create product documentation 42 | 43 | #### Agent-OS Directory Structure 44 | 45 | ``` 46 | agent-os/ 47 | ├── config.yml # Agent-OS configuration 48 | ├── product/ # Product documentation 49 | │ ├── mission.md # Product mission and goals 50 | │ ├── roadmap.md # Feature roadmap 51 | │ └── tech-stack.md # Technology stack 52 | ├── specs/ # Feature specifications 53 | │ └── YYYY-MM-DD-feature-name/ 54 | │ ├── planning/ 55 | │ │ ├── requirements.md 56 | │ │ └── visuals/ 57 | │ ├── spec.md 58 | │ └── tasks.md 59 | └── standards/ # Coding standards (as skills) 60 | ``` 61 | 62 | #### How Agent-OS Works with Claude OS 63 | 64 | Agent-OS agents integrate deeply with Claude OS: 65 | - **Search memories** before creating specs (avoid reinventing the wheel) 66 | - **Save decisions** to project_memories during specification 67 | - **Reference patterns** from previous work 68 | - **Build knowledge** over time 69 | 70 | #### Best Practices 71 | 72 | - **Always start with `/new-spec`** for new features 73 | - **Provide visual mockups** when available (speeds up requirements) 74 | - **Answer questions thoughtfully** (agents ask 1-3 at a time now!) 75 | - **Reference existing code** (agents will search for patterns) 76 | - **Let agents guide you** through the structured workflow 77 | 78 | **See `agent-os/README.md` for detailed Agent-OS documentation.** 79 | -------------------------------------------------------------------------------- /templates/commands/claude-os-search.md: -------------------------------------------------------------------------------- 1 | # Claude OS Search Command 2 | 3 | You are helping search Claude OS knowledge bases for relevant information. 4 | 5 | ## User's Request 6 | 7 | The user ran: `/claude-os-search [query]` 8 | 9 | ## Your Task 10 | 11 | 1. **Parse the query**: 12 | - Extract search terms from the command 13 | - Identify if user specified a KB name (e.g., "search myapp-project_memories for auth patterns") 14 | - Default to searching `{project}-project_memories` if not specified 15 | 16 | 2. **Execute the search**: 17 | - Use the `mcp__claude-os__search_knowledge_base` tool (note: internally it might still show as `mcp__code-forge__search_knowledge_base` but it's Claude OS) 18 | - Set `kb_name` to the target KB (default: `{project}-project_memories`) 19 | - Set `query` to the search terms 20 | - Consider using `use_hybrid: true` for better results 21 | - Consider using `use_rerank: true` for relevance ranking 22 | 23 | 3. **Present results clearly**: 24 | - Show relevant excerpts from matched documents 25 | - Include document titles and relevance scores if available 26 | - Summarize key findings 27 | - Provide actionable insights 28 | 29 | 4. **If no results**: 30 | - Try broader search terms 31 | - Try different KB (e.g., search `{project}-knowledge_docs` instead) 32 | - Suggest user save this as new knowledge if it's something we discover 33 | 34 | ## Available KBs 35 | 36 | - `{project}-project_memories` - **Search here first** - Project decisions, patterns, solutions 37 | - `{project}-project_profile` - Architecture, standards, practices 38 | - `{project}-project_index` - Codebase index 39 | - `{project}-knowledge_docs` - Documentation and guides 40 | 41 | ## Search Features 42 | 43 | - **Basic search**: Simple vector similarity search 44 | - **Hybrid search** (`use_hybrid: true`): Combines vector + keyword (BM25) search 45 | - **Reranking** (`use_rerank: true`): Re-orders results for better relevance 46 | - **Agentic RAG** (`use_agentic: true`): For complex multi-step queries 47 | 48 | ## Examples 49 | 50 | **Example 1**: `/claude-os-search appointment scheduling logic` 51 | - Search: `{project}-project_memories` for appointment-related content 52 | - Use hybrid search for better recall 53 | 54 | **Example 2**: `/claude-os-search API integration patterns in myapp-knowledge_docs` 55 | - Search: `myapp-knowledge_docs` KB specifically 56 | - Look for integration documentation 57 | 58 | **Example 3**: `/claude-os-search complex query about how models interact` 59 | - Use: `use_agentic: true` for multi-step reasoning 60 | 61 | ## After Search 62 | 63 | - Apply found knowledge to current task 64 | - Reference what you learned: "Based on what I found in Claude OS..." 65 | - If you discover new insights during work, save them back to Claude OS 66 | - Update or correct outdated information 67 | 68 | ## Remember 69 | 70 | Claude OS is YOUR memory - search it proactively when: 71 | - Starting new features (check for similar patterns) 72 | - Debugging (check for known issues/solutions) 73 | - Making decisions (check for previous context) 74 | - Unsure about conventions (check standards/practices) 75 | 76 | **Be proactive!** Don't wait for user to tell you to search - do it automatically when it would help. 77 | -------------------------------------------------------------------------------- /frontend/e2e/configure-modal.spec.ts: -------------------------------------------------------------------------------- 1 | import { test, expect } from '@playwright/test'; 2 | 3 | test.describe('Configure Modal (Issue #14)', () => { 4 | test('Configure modal has proper backdrop overlay', async ({ page }) => { 5 | // Navigate to the app 6 | await page.goto('/app'); 7 | 8 | // Wait for page to load 9 | await page.waitForLoadState('networkidle'); 10 | 11 | // Check if there are any projects listed 12 | const projectCards = page.locator('[class*="card"]').filter({ hasText: /Configure|Settings/ }); 13 | 14 | // If no projects, check that we see the "No projects" message or create project button 15 | const noProjectsMessage = page.getByText('No projects yet'); 16 | const hasNoProjects = await noProjectsMessage.isVisible().catch(() => false); 17 | 18 | if (hasNoProjects) { 19 | console.log('No projects found - skipping configure modal test'); 20 | return; 21 | } 22 | 23 | // Find and click the Settings/Configure button on first project 24 | const settingsButton = page.locator('button').filter({ has: page.locator('svg') }).first(); 25 | 26 | // Look for a settings icon button 27 | const configureButton = page.locator('[title="Setup project"], [title="Configure"]').first(); 28 | 29 | if (await configureButton.isVisible()) { 30 | await configureButton.click(); 31 | 32 | // Wait for modal to appear 33 | await page.waitForTimeout(500); 34 | 35 | // Check that the modal backdrop exists with proper styling 36 | const backdrop = page.locator('.fixed.inset-0').filter({ has: page.locator('.card') }); 37 | 38 | // Verify backdrop has semi-transparent background (bg-black/50) 39 | const backdropElement = backdrop.first(); 40 | if (await backdropElement.isVisible()) { 41 | const bgClass = await backdropElement.getAttribute('class'); 42 | 43 | // Check for semi-transparent background class 44 | expect(bgClass).toContain('bg-black/50'); 45 | 46 | // Verify clicking outside closes the modal 47 | await backdropElement.click({ position: { x: 10, y: 10 } }); 48 | 49 | // Modal should be closed 50 | await expect(backdrop).not.toBeVisible({ timeout: 2000 }); 51 | 52 | console.log('✅ Configure modal has proper backdrop and closes on outside click'); 53 | } 54 | } else { 55 | console.log('No configure button found'); 56 | } 57 | }); 58 | 59 | test('Configure modal can be closed with X button', async ({ page }) => { 60 | await page.goto('/app'); 61 | await page.waitForLoadState('networkidle'); 62 | 63 | // Find configure/settings button 64 | const configureButton = page.locator('[title="Setup project"]').first(); 65 | 66 | if (await configureButton.isVisible().catch(() => false)) { 67 | await configureButton.click(); 68 | await page.waitForTimeout(500); 69 | 70 | // Find and click the close button (X) 71 | const closeButton = page.locator('button').filter({ hasText: '✕' }); 72 | await closeButton.click(); 73 | 74 | // Verify modal is closed 75 | const modal = page.locator('.fixed.inset-0').filter({ has: page.locator('.card') }); 76 | await expect(modal).not.toBeVisible({ timeout: 2000 }); 77 | 78 | console.log('✅ Configure modal closes with X button'); 79 | } 80 | }); 81 | }); 82 | -------------------------------------------------------------------------------- /scripts/entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # ============================================================================ 4 | # Claude OS Docker Container Entrypoint 5 | # ============================================================================ 6 | # This script runs inside the Docker container and starts the MCP server. 7 | # ============================================================================ 8 | 9 | set -e # Exit on error 10 | 11 | # Colors 12 | RED='\033[0;31m' 13 | GREEN='\033[0;32m' 14 | YELLOW='\033[1;33m' 15 | BLUE='\033[0;34m' 16 | PURPLE='\033[0;35m' 17 | NC='\033[0m' # No Color 18 | 19 | # Print functions 20 | print_status() { 21 | echo -e "${BLUE}[INFO]${NC} $1" 22 | } 23 | 24 | print_success() { 25 | echo -e "${GREEN}[✓]${NC} $1" 26 | } 27 | 28 | print_warning() { 29 | echo -e "${YELLOW}[!]${NC} $1" 30 | } 31 | 32 | print_error() { 33 | echo -e "${RED}[✗]${NC} $1" 34 | } 35 | 36 | # Banner 37 | echo -e "${PURPLE}" 38 | cat << "EOF" 39 | ____ _ _____ 40 | / ___|___ __| | ___ | ___|__ _ __ __ _ ___ 41 | | | / _ \ / _` |/ _ \ | |_ / _ \| '__/ _` |/ _ \ 42 | | |__| (_) | (_| | __/ | _| (_) | | | (_| | __/ 43 | \____\___/ \__,_|\___| |_| \___/|_| \__, |\___| 44 | |___/ 45 | MCP Server Container 46 | EOF 47 | echo -e "${NC}" 48 | 49 | print_status "Starting Claude OS MCP Server..." 50 | 51 | # ============================================================================ 52 | # Wait for Dependencies 53 | # ============================================================================ 54 | print_status "Waiting for dependencies to be ready..." 55 | 56 | # Wait for PostgreSQL 57 | print_status "Checking PostgreSQL connection..." 58 | MAX_RETRIES=30 59 | RETRY_COUNT=0 60 | 61 | while [ $RETRY_COUNT -lt $MAX_RETRIES ]; do 62 | if python3 -c "import psycopg2; psycopg2.connect(host='${POSTGRES_HOST}', port=${POSTGRES_PORT}, dbname='${POSTGRES_DB}', user='${POSTGRES_USER}')" 2>/dev/null; then 63 | print_success "PostgreSQL is ready" 64 | break 65 | fi 66 | RETRY_COUNT=$((RETRY_COUNT + 1)) 67 | if [ $RETRY_COUNT -eq $MAX_RETRIES ]; then 68 | print_error "PostgreSQL is not available after ${MAX_RETRIES} attempts" 69 | exit 1 70 | fi 71 | echo -n "." 72 | sleep 1 73 | done 74 | 75 | # Wait for Ollama 76 | print_status "Checking Ollama connection..." 77 | RETRY_COUNT=0 78 | 79 | while [ $RETRY_COUNT -lt $MAX_RETRIES ]; do 80 | if curl -s "${OLLAMA_HOST}/api/tags" > /dev/null 2>&1; then 81 | print_success "Ollama is ready" 82 | break 83 | fi 84 | RETRY_COUNT=$((RETRY_COUNT + 1)) 85 | if [ $RETRY_COUNT -eq $MAX_RETRIES ]; then 86 | print_warning "Ollama is not available, but continuing anyway..." 87 | break 88 | fi 89 | echo -n "." 90 | sleep 1 91 | done 92 | 93 | # ============================================================================ 94 | # Start MCP Server 95 | # ============================================================================ 96 | print_success "All dependencies ready!" 97 | print_status "Starting MCP Server on port ${MCP_SERVER_PORT}..." 98 | 99 | # Start the MCP server 100 | exec python3 mcp_server/server.py 101 | 102 | -------------------------------------------------------------------------------- /templates/README.md: -------------------------------------------------------------------------------- 1 | # Claude OS Templates 2 | 3 | This directory contains all template files used when initializing a new project with Claude OS. 4 | 5 | ## Directory Structure 6 | 7 | ``` 8 | templates/ 9 | ├── commands/ # Slash command templates (symlinked to projects) 10 | ├── skills/ # Skill templates (symlinked to projects) 11 | ├── agents/ # Agent templates (project-specific) 12 | ├── project-files/ # Files created during project init 13 | │ ├── CLAUDE.md.template 14 | │ ├── .claude-os/ 15 | │ │ ├── config.json.template 16 | │ │ ├── hooks.json.template 17 | │ │ └── .gitignore 18 | │ └── README.md 19 | └── README.md # This file 20 | ``` 21 | 22 | ## Template Variables 23 | 24 | Templates use `{{VARIABLE}}` syntax for placeholders that get replaced during project initialization: 25 | 26 | ### Common Variables 27 | 28 | - `{{PROJECT_NAME}}` - Project name (e.g., "my-app") 29 | - `{{PROJECT_DESCRIPTION}}` - Brief project description 30 | - `{{TECH_STACK}}` - Technology stack (e.g., "Ruby on Rails, MySQL") 31 | - `{{DATABASE}}` - Database system (e.g., "PostgreSQL", "MySQL") 32 | - `{{DEV_ENVIRONMENT}}` - Dev environment (e.g., "Docker", "Local") 33 | - `{{CLAUDE_OS_URL}}` - Claude OS server URL (default: http://localhost:8051) 34 | - `{{DOCS_PATHS}}` - JSON array of documentation paths 35 | - `{{CREATED_AT}}` - ISO timestamp of creation 36 | - `{{PROJECT_SPECIFIC_CONTENT}}` - Custom project content 37 | - `{{DEVELOPMENT_GUIDELINES}}` - Project-specific guidelines 38 | - `{{COMMON_TASKS}}` - Common development tasks 39 | - `{{BUSINESS_RULES}}` - Key business rules 40 | 41 | ## How Templates Are Used 42 | 43 | When running `/claude-os-init`: 44 | 45 | 1. **Commands & Skills** - Symlinked from `templates/commands/` and `templates/skills/` to project's `.claude/` directory 46 | 2. **Project Files** - Copied from `templates/project-files/` with variables replaced 47 | 3. **Knowledge Bases** - Created via API with project-specific names 48 | 4. **MCP Configuration** - Updated in `~/.claude/mcp-servers/` with new project 49 | 50 | ## Adding New Templates 51 | 52 | ### New Command Template 53 | 54 | 1. Create file in `templates/commands/my-command.md` 55 | 2. Add command logic 56 | 3. Will be automatically available after `/claude-os-init` 57 | 58 | ### New Skill Template 59 | 60 | 1. Create directory in `templates/skills/my-skill/` 61 | 2. Add `SKILL.md` and any scripts 62 | 3. Will be automatically available after `/claude-os-init` 63 | 64 | ### Updating CLAUDE.md Template 65 | 66 | Edit `templates/project-files/CLAUDE.md.template` to add: 67 | - New sections 68 | - Updated workflow instructions 69 | - Additional context 70 | 71 | Changes will apply to NEW projects only. Existing projects keep their CLAUDE.md unchanged. 72 | 73 | ## Consolidation Scripts 74 | 75 | See the `cli/` directory in this repository for scripts to: 76 | - Move commands from `~/.claude/commands/` to `templates/commands/` 77 | - Move skills from `~/.claude/skills/` to `templates/skills/` 78 | - Update existing projects to use templates 79 | 80 | ## For Coworkers 81 | 82 | When you clone Claude OS and run `./install.sh`, these templates are: 83 | 1. Registered with your Claude CLI 84 | 2. Available for new project initialization 85 | 3. Ready to use with `/claude-os-init` 86 | 87 | Then cd to any project and run `/claude-os-init` to connect it to Claude OS! 88 | -------------------------------------------------------------------------------- /frontend/src/lib/auth.tsx: -------------------------------------------------------------------------------- 1 | import { createContext, useContext, useState, useEffect, ReactNode } from 'react'; 2 | 3 | const API_BASE = 'http://localhost:8051'; 4 | 5 | interface AuthContextType { 6 | isAuthenticated: boolean; 7 | isAuthEnabled: boolean; 8 | isLoading: boolean; 9 | user: { email: string } | null; 10 | login: (email: string, password: string) => Promise; 11 | logout: () => void; 12 | } 13 | 14 | const AuthContext = createContext(undefined); 15 | 16 | export function AuthProvider({ children }: { children: ReactNode }) { 17 | const [isAuthenticated, setIsAuthenticated] = useState(false); 18 | const [isAuthEnabled, setIsAuthEnabled] = useState(true); 19 | const [isLoading, setIsLoading] = useState(true); 20 | const [user, setUser] = useState<{ email: string } | null>(null); 21 | 22 | useEffect(() => { 23 | checkAuthStatus(); 24 | }, []); 25 | 26 | const checkAuthStatus = async () => { 27 | try { 28 | // Check if auth is enabled 29 | const statusRes = await fetch(`${API_BASE}/api/auth/status`); 30 | if (statusRes.ok) { 31 | const statusData = await statusRes.json(); 32 | setIsAuthEnabled(statusData.auth_enabled); 33 | 34 | if (!statusData.auth_enabled) { 35 | setIsAuthenticated(true); 36 | setIsLoading(false); 37 | return; 38 | } 39 | } 40 | 41 | // Check if user is already logged in 42 | const token = localStorage.getItem('auth_token'); 43 | if (token) { 44 | const meRes = await fetch(`${API_BASE}/api/auth/me`, { 45 | headers: { Authorization: `Bearer ${token}` } 46 | }); 47 | if (meRes.ok) { 48 | const userData = await meRes.json(); 49 | setUser(userData); 50 | setIsAuthenticated(true); 51 | } else { 52 | localStorage.removeItem('auth_token'); 53 | } 54 | } 55 | } catch (error) { 56 | // If we can't reach the server, assume auth is disabled for local dev 57 | console.warn('Could not check auth status:', error); 58 | setIsAuthEnabled(false); 59 | setIsAuthenticated(true); 60 | } finally { 61 | setIsLoading(false); 62 | } 63 | }; 64 | 65 | const login = async (email: string, password: string) => { 66 | const res = await fetch(`${API_BASE}/api/auth/login`, { 67 | method: 'POST', 68 | headers: { 'Content-Type': 'application/json' }, 69 | body: JSON.stringify({ email, password }) 70 | }); 71 | 72 | if (!res.ok) { 73 | const error = await res.json(); 74 | throw new Error(error.detail || 'Login failed'); 75 | } 76 | 77 | const data = await res.json(); 78 | localStorage.setItem('auth_token', data.access_token); 79 | setUser({ email }); 80 | setIsAuthenticated(true); 81 | }; 82 | 83 | const logout = () => { 84 | localStorage.removeItem('auth_token'); 85 | setUser(null); 86 | setIsAuthenticated(false); 87 | }; 88 | 89 | return ( 90 | 91 | {children} 92 | 93 | ); 94 | } 95 | 96 | export function useAuth() { 97 | const context = useContext(AuthContext); 98 | if (context === undefined) { 99 | throw new Error('useAuth must be used within an AuthProvider'); 100 | } 101 | return context; 102 | } 103 | -------------------------------------------------------------------------------- /tests/test_embeddings.py: -------------------------------------------------------------------------------- 1 | """ 2 | Tests for embedding generation. 3 | """ 4 | 5 | import pytest 6 | import numpy as np 7 | from unittest.mock import patch, MagicMock 8 | 9 | 10 | @pytest.mark.integration 11 | @pytest.mark.embeddings 12 | class TestOllamaEmbeddings: 13 | """Test Ollama embedding generation.""" 14 | 15 | @patch('llama_index.embeddings.ollama.OllamaEmbedding') 16 | def test_embedding_generation(self, mock_ollama): 17 | """Test that embeddings are generated correctly.""" 18 | # Mock the embedding model 19 | mock_instance = MagicMock() 20 | mock_instance.get_text_embedding.return_value = np.random.randn(768).tolist() 21 | mock_ollama.return_value = mock_instance 22 | 23 | from llama_index.embeddings.ollama import OllamaEmbedding 24 | 25 | embed_model = OllamaEmbedding( 26 | model_name="nomic-embed-text", 27 | base_url="http://localhost:11434" 28 | ) 29 | 30 | embedding = embed_model.get_text_embedding("test text") 31 | 32 | assert len(embedding) == 768 33 | assert all(isinstance(x, float) for x in embedding) 34 | 35 | def test_embedding_consistency(self): 36 | """Test that same text produces same embedding.""" 37 | from llama_index.embeddings.ollama import OllamaEmbedding 38 | 39 | embed_model = OllamaEmbedding( 40 | model_name="nomic-embed-text", 41 | base_url="http://localhost:11434" 42 | ) 43 | 44 | text = "This is a test sentence for embedding consistency." 45 | 46 | embedding1 = embed_model.get_text_embedding(text) 47 | embedding2 = embed_model.get_text_embedding(text) 48 | 49 | # Should be identical (or very close due to floating point) 50 | np.testing.assert_array_almost_equal(embedding1, embedding2, decimal=5) 51 | 52 | def test_embedding_dimension(self): 53 | """Test that embeddings have correct dimension.""" 54 | from llama_index.embeddings.ollama import OllamaEmbedding 55 | 56 | embed_model = OllamaEmbedding( 57 | model_name="nomic-embed-text", 58 | base_url="http://localhost:11434" 59 | ) 60 | 61 | texts = [ 62 | "Short text", 63 | "This is a longer text with more words and content.", 64 | "A" * 1000 # Very long text 65 | ] 66 | 67 | for text in texts: 68 | embedding = embed_model.get_text_embedding(text) 69 | assert len(embedding) == 768, f"Expected 768 dimensions, got {len(embedding)}" 70 | 71 | 72 | @pytest.mark.unit 73 | class TestEmbeddingUtils: 74 | """Test embedding utility functions.""" 75 | 76 | def test_cosine_similarity(self): 77 | """Test cosine similarity calculation.""" 78 | # Identical vectors should have similarity of 1.0 79 | vec1 = [1.0, 0.0, 0.0] 80 | vec2 = [1.0, 0.0, 0.0] 81 | 82 | similarity = 1 - np.dot(vec1, vec2) / (np.linalg.norm(vec1) * np.linalg.norm(vec2)) 83 | assert abs(similarity) < 0.001 # Should be ~0 (distance), so similarity ~1 84 | 85 | def test_embedding_normalization(self): 86 | """Test that embeddings can be normalized.""" 87 | embedding = np.random.randn(768) 88 | normalized = embedding / np.linalg.norm(embedding) 89 | 90 | # Normalized vector should have magnitude 1 91 | assert abs(np.linalg.norm(normalized) - 1.0) < 0.001 92 | -------------------------------------------------------------------------------- /tests/README.md: -------------------------------------------------------------------------------- 1 | # Claude OS Test Suite 2 | 3 | Comprehensive tests for the Claude OS RAG system. 4 | 5 | ## Setup 6 | 7 | 1. **Install test dependencies:** 8 | ```bash 9 | pip install -r requirements.txt 10 | ``` 11 | 12 | 2. **Set environment variables (optional):** 13 | ```bash 14 | export TEST_OLLAMA_HOST=http://localhost:11434 15 | ``` 16 | 17 | Note: Tests use SQLite database which is automatically created in the test environment. 18 | 19 | ## Running Tests 20 | 21 | ### Run all tests: 22 | ```bash 23 | pytest 24 | ``` 25 | 26 | ### Run specific test categories: 27 | ```bash 28 | # Unit tests only (fast, no external dependencies) 29 | pytest -m unit 30 | 31 | # Integration tests (require database, Ollama) 32 | pytest -m integration 33 | 34 | # Vector operation tests 35 | pytest -m vector 36 | 37 | # RAG engine tests 38 | pytest -m rag 39 | 40 | # API endpoint tests 41 | pytest -m api 42 | ``` 43 | 44 | ### Run specific test files: 45 | ```bash 46 | pytest tests/test_pg_vector.py 47 | pytest tests/test_rag_engine.py 48 | pytest tests/test_api.py 49 | ``` 50 | 51 | ### Run with coverage: 52 | ```bash 53 | pytest --cov=app --cov-report=html 54 | # Open htmlcov/index.html to view coverage report 55 | ``` 56 | 57 | ### Run with verbose output: 58 | ```bash 59 | pytest -v 60 | ``` 61 | 62 | ### Run and stop on first failure: 63 | ```bash 64 | pytest -x 65 | ``` 66 | 67 | ## Test Structure 68 | 69 | - **`conftest.py`** - Shared fixtures and configuration 70 | - **`test_rag_engine.py`** - RAG engine functionality 71 | - **`test_embeddings.py`** - Embedding generation 72 | - **`test_document_processing.py`** - Document ingestion and chunking 73 | - **`test_api.py`** - FastAPI endpoints 74 | 75 | ## Test Markers 76 | 77 | Tests are categorized with markers: 78 | 79 | - `@pytest.mark.unit` - Fast unit tests, no external dependencies 80 | - `@pytest.mark.integration` - Integration tests requiring database/Ollama 81 | - `@pytest.mark.slow` - Tests that may take several seconds 82 | - `@pytest.mark.embeddings` - Tests involving embedding generation 83 | - `@pytest.mark.vector` - Tests involving vector operations 84 | - `@pytest.mark.rag` - Tests involving RAG engine 85 | - `@pytest.mark.api` - Tests involving API endpoints 86 | 87 | ## Fixtures 88 | 89 | Common fixtures available in all tests: 90 | 91 | - `test_db_config` - Database configuration 92 | - `db_connection` - Test database connection (session-scoped) 93 | - `clean_db` - Clean database before each test 94 | - `sample_kb` - Sample knowledge base 95 | - `sample_embedding` - Sample 768-dimensional embedding 96 | - `sample_documents` - Sample documents with embeddings 97 | - `mock_ollama_embedding` - Mock Ollama embedding model 98 | - `mock_ollama_llm` - Mock Ollama LLM 99 | - `sample_text_file` - Sample text file 100 | - `sample_pdf_file` - Sample PDF file 101 | - `sample_markdown_file` - Sample Markdown file 102 | - `api_client` - FastAPI test client 103 | 104 | ## CI/CD Integration 105 | 106 | Tests can be run in CI/CD pipelines: 107 | 108 | ```yaml 109 | # Example GitHub Actions workflow 110 | - name: Run tests 111 | run: | 112 | pytest --cov=app --cov-report=xml 113 | 114 | - name: Upload coverage 115 | uses: codecov/codecov-action@v3 116 | ``` 117 | 118 | ## Troubleshooting 119 | 120 | ### Ollama connection errors: 121 | - Ensure Ollama is running: `curl http://localhost:11434/api/tags` 122 | - Check TEST_OLLAMA_HOST environment variable 123 | 124 | ### Import errors: 125 | - Ensure you're in the project root directory 126 | - Install all dependencies: `pip install -r requirements.txt` 127 | 128 | -------------------------------------------------------------------------------- /app/core/health.py: -------------------------------------------------------------------------------- 1 | """ 2 | Health check utilities for monitoring service connectivity. 3 | """ 4 | 5 | import logging 6 | import time 7 | from typing import Dict 8 | 9 | import requests 10 | 11 | from app.core.config import Config 12 | 13 | logger = logging.getLogger(__name__) 14 | 15 | 16 | def check_ollama_health() -> Dict[str, any]: 17 | """ 18 | Check Ollama service health and available models. 19 | 20 | Returns: 21 | dict: Status information with 'status', 'models', and optional 'error' 22 | """ 23 | try: 24 | response = requests.get( 25 | f"{Config.OLLAMA_HOST}/api/tags", 26 | timeout=5 27 | ) 28 | response.raise_for_status() 29 | 30 | data = response.json() 31 | models = [model.get("name", "unknown") for model in data.get("models", [])] 32 | 33 | return { 34 | "status": "healthy", 35 | "models": models, 36 | "url": Config.OLLAMA_HOST 37 | } 38 | except requests.exceptions.ConnectionError as e: 39 | logger.warning(f"Ollama connection failed: {e}") 40 | return { 41 | "status": "unhealthy", 42 | "error": "Connection refused - is Ollama running?", 43 | "url": Config.OLLAMA_HOST 44 | } 45 | except requests.exceptions.Timeout as e: 46 | logger.warning(f"Ollama timeout: {e}") 47 | return { 48 | "status": "unhealthy", 49 | "error": "Request timed out", 50 | "url": Config.OLLAMA_HOST 51 | } 52 | except Exception as e: 53 | logger.error(f"Ollama health check failed: {e}") 54 | return { 55 | "status": "unhealthy", 56 | "error": str(e), 57 | "url": Config.OLLAMA_HOST 58 | } 59 | 60 | 61 | def check_sqlite_health() -> Dict[str, any]: 62 | """ 63 | Check SQLite database health. 64 | 65 | Returns: 66 | dict: Status information with 'status' and optional 'error' 67 | """ 68 | try: 69 | from app.core.sqlite_manager import get_sqlite_manager 70 | 71 | db_manager = get_sqlite_manager() 72 | # Try to list collections as a health check 73 | collections = db_manager.list_collections() 74 | 75 | return { 76 | "status": "healthy", 77 | "collections": len(collections) 78 | } 79 | except Exception as e: 80 | logger.warning(f"SQLite database check failed: {e}") 81 | return { 82 | "status": "unhealthy", 83 | "error": f"Database access failed: {str(e)}" 84 | } 85 | 86 | 87 | def wait_for_services(max_retries: int = 30, delay: int = 2) -> bool: 88 | """ 89 | Wait for both Ollama and SQLite services to become healthy. 90 | 91 | Args: 92 | max_retries: Maximum number of retry attempts 93 | delay: Seconds to wait between retries 94 | 95 | Returns: 96 | bool: True if both services are healthy, False if max retries exceeded 97 | """ 98 | logger.info("Waiting for services to become healthy...") 99 | 100 | for attempt in range(1, max_retries + 1): 101 | ollama_status = check_ollama_health() 102 | sqlite_status = check_sqlite_health() 103 | 104 | if ollama_status["status"] == "healthy" and sqlite_status["status"] == "healthy": 105 | logger.info(f"All services healthy after {attempt} attempts") 106 | return True 107 | 108 | logger.info( 109 | f"Attempt {attempt}/{max_retries}: " 110 | f"Ollama={ollama_status['status']}, " 111 | f"SQLite={sqlite_status['status']}" 112 | ) 113 | 114 | if attempt < max_retries: 115 | time.sleep(delay) 116 | 117 | logger.error(f"Services did not become healthy after {max_retries} attempts") 118 | return False 119 | 120 | -------------------------------------------------------------------------------- /templates/skills/remember-this/SKILL.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: remember-this 3 | description: "Capture conversation context, insights, or discoveries and save them as markdown documents to Claude OS knowledge bases. Use when you want to save important information like 'remember this:', design decisions, troubleshooting solutions, or architectural patterns for future reference." 4 | allowed-tools: Read, Write, Bash, Task 5 | --- 6 | 7 | # Remember This Skill 8 | 9 | ## Purpose 10 | 11 | Automatically capture important context from our conversations and save it to Claude OS knowledge bases so I can reference it in future sessions. Perfect for: 12 | 13 | - Design decisions and rationale 14 | - Troubleshooting solutions discovered 15 | - Architectural patterns you've explained 16 | - Edge cases encountered 17 | - Integration patterns 18 | - Best practices you've shared 19 | - Complex system behavior 20 | 21 | ## How to Use 22 | 23 | Simply say one of: 24 | - **"Remember this: [information]"** 25 | - **"Save this: [information]"** 26 | - **"Document this: [information]"** 27 | - **"Remember: [explanation]"** 28 | 29 | ## What Happens 30 | 31 | When you invoke this skill: 32 | 33 | 1. **I extract the key information** from your statement 34 | 2. **I create a formatted markdown document** with proper structure 35 | 3. **I upload it to Claude OS** (default: {project}-project_memories KB) 36 | 4. **I confirm what was saved** and where 37 | 5. **I reference it in future conversations** automatically 38 | 39 | ## Document Structure 40 | 41 | ```markdown 42 | # [Topic Title] 43 | 44 | **Date Saved**: [Auto-generated] 45 | **Context**: [Where this came from] 46 | **Category**: [Architecture/Integration/Pattern/Troubleshooting/etc] 47 | 48 | [Main content in well-structured format] 49 | 50 | ## Key Takeaways 51 | - Bullet point 1 52 | - Bullet point 2 53 | 54 | ## Related Topics 55 | - Links to related documentation 56 | ``` 57 | 58 | ## Examples 59 | 60 | ### Example 1: Remember a Pattern 61 | ``` 62 | User: "Remember this: When creating a new service, always follow this structure: 63 | initialize with domain objects and params, have a single perform method that returns 64 | model on success or error string on failure, use private methods for complex logic." 65 | 66 | → Saves to: "Service Pattern Guide.md" in project KB 67 | → I reference it: "Like the pattern you documented, services should..." 68 | ``` 69 | 70 | ### Example 2: Save a Solution 71 | ``` 72 | User: "Save this: Fixed the N+1 query problem in AppointmentsScheduler by adding 73 | .includes(:block_settings, :children) to prevent multiple DB queries." 74 | 75 | → Saves to: "Query Optimization Solutions.md" 76 | → I use it: "We can apply the same .includes strategy here..." 77 | ``` 78 | 79 | ### Example 3: Document an Architecture Decision 80 | ``` 81 | User: "Remember: Block model uses acts_as_tree for hierarchical structure because 82 | we need semantic role-based organization of child blocks, not just a flat list." 83 | 84 | → Saves to: "Blocks System Decisions.md" 85 | → I reference it: "Following the hierarchical pattern you documented..." 86 | ``` 87 | 88 | ## Customization 89 | 90 | You can specify: 91 | 92 | - **KB Name**: "Remember this [content] - save to my-project-memories" 93 | - **Document Title**: "Remember this [content] - as 'My Custom Title'" 94 | - **Tags/Category**: "Remember this [content] - category: Integration" 95 | 96 | ## Benefits 97 | 98 | ✅ **Build institutional knowledge** over time 99 | ✅ **I remember context** across sessions 100 | ✅ **Reduces repetition** of explanations 101 | ✅ **Creates searchable archive** of decisions 102 | ✅ **Helps with onboarding** (your knowledge is documented) 103 | ✅ **Perfect for discoveries** made during debugging 104 | 105 | --- 106 | 107 | **Pro Tip**: Use this skill liberally! Every insight you share gets permanently indexed and makes me a better developer for your project. 108 | -------------------------------------------------------------------------------- /frontend/src/assets/react.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /scripts/generate_diagnostic.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Generate diagnostic report for troubleshooting 3 | 4 | OUTPUT_FILE="${1:-/tmp/claude-os-diagnostic-$(date +%Y%m%d_%H%M%S).txt}" 5 | 6 | cat > "$OUTPUT_FILE" << EOF 7 | Claude OS Installation Diagnostic Report 8 | Generated: $(date) 9 | ═══════════════════════════════════════════════════════════════ 10 | 11 | INSTALLATION SUMMARY 12 | ─────────────────────────────────────────────────────────────── 13 | Status: ${INSTALL_STATUS:-UNKNOWN} 14 | Errors: ${ERROR_COUNT:-0} 15 | Warnings: ${WARNING_COUNT:-0} 16 | 17 | ${ERROR_LOG} 18 | 19 | SYSTEM INFORMATION 20 | ─────────────────────────────────────────────────────────────── 21 | OS: $(uname -s) $(uname -r) 22 | Architecture: $(uname -m) 23 | Hostname: $(hostname) 24 | 25 | PYTHON INFORMATION 26 | ─────────────────────────────────────────────────────────────── 27 | Default Python: $(python3 --version 2>&1 || echo "Not found") 28 | Python 3.12: $(python3.12 --version 2>&1 || echo "Not found") 29 | Python 3.11: $(python3.11 --version 2>&1 || echo "Not found") 30 | 31 | Detected Python: ${PYTHON_VERSION:-Not detected} 32 | Python Command: ${PYTHON_CMD:-Not set} 33 | 34 | ENVIRONMENT 35 | ─────────────────────────────────────────────────────────────── 36 | Claude OS Directory: ${CLAUDE_OS_DIR:-Not set} 37 | User Claude Directory: ${USER_CLAUDE_DIR:-Not set} 38 | 39 | Virtual Environment: $([ -d "${CLAUDE_OS_DIR}/venv" ] && echo "Created" || echo "Not created") 40 | $([ -d "${CLAUDE_OS_DIR}/venv" ] && ${CLAUDE_OS_DIR}/venv/bin/python --version 2>&1 || echo "") 41 | 42 | DEPENDENCIES 43 | ─────────────────────────────────────────────────────────────── 44 | $([ -d "${CLAUDE_OS_DIR}/venv" ] && ${CLAUDE_OS_DIR}/venv/bin/pip list 2>&1 | grep -E "(tree-sitter|llama-index|fastapi)" || echo "Virtual environment not available") 45 | 46 | FILES CREATED 47 | ─────────────────────────────────────────────────────────────── 48 | Commands: $(ls -1 ${USER_CLAUDE_DIR}/commands/claude-os-*.md 2>/dev/null | wc -l | xargs) symlinks 49 | Skills: $(ls -1d ${USER_CLAUDE_DIR}/skills/{memory,initialize-project,remember-this} 2>/dev/null | wc -l | xargs) symlinks 50 | start.sh: $([ -f "${CLAUDE_OS_DIR}/start.sh" ] && echo "Created" || echo "Not created") 51 | config.json: $([ -f "${CLAUDE_OS_DIR}/claude-os-config.json" ] && echo "Created" || echo "Not created") 52 | MCP config: $([ -f "${USER_CLAUDE_DIR}/mcp-servers/code-forge.json" ] && echo "Created" || echo "Not created") 53 | 54 | SYMLINK DETAILS 55 | ─────────────────────────────────────────────────────────────── 56 | $(ls -la ${USER_CLAUDE_DIR}/commands/claude-os-*.md 2>&1 | head -10) 57 | 58 | $(ls -la ${USER_CLAUDE_DIR}/skills/{memory,initialize-project,remember-this} 2>&1 | head -5) 59 | 60 | GIT INFORMATION 61 | ─────────────────────────────────────────────────────────────── 62 | Git: $(git --version 2>&1 || echo "Not found") 63 | Claude OS Repo: $(cd ${CLAUDE_OS_DIR} 2>/dev/null && git remote -v 2>&1 | head -2 || echo "Not a git repo") 64 | 65 | NETWORK CONNECTIVITY 66 | ─────────────────────────────────────────────────────────────── 67 | GitHub: $(curl -s -o /dev/null -w "%{http_code}" https://github.com --connect-timeout 5 || echo "Failed") 68 | PyPI: $(curl -s -o /dev/null -w "%{http_code}" https://pypi.org --connect-timeout 5 || echo "Failed") 69 | 70 | DISK SPACE 71 | ─────────────────────────────────────────────────────────────── 72 | Available: $(df -h ${CLAUDE_OS_DIR} | tail -1 | awk '{print $4}') 73 | Used by Claude OS: $(du -sh ${CLAUDE_OS_DIR} 2>/dev/null | cut -f1 || echo "Unknown") 74 | 75 | RECENT LOGS 76 | ─────────────────────────────────────────────────────────────── 77 | $(tail -50 ${CLAUDE_OS_DIR}/logs/*.log 2>/dev/null | head -20 || echo "No logs available") 78 | 79 | ═══════════════════════════════════════════════════════════════ 80 | End of Diagnostic Report 81 | ═══════════════════════════════════════════════════════════════ 82 | 83 | To report this issue: 84 | 1. Create GitHub issue: https://github.com/brobertsaz/claude-os/issues/new 85 | 2. Or run: ./scripts/report_error.sh $OUTPUT_FILE 86 | EOF 87 | 88 | echo "$OUTPUT_FILE" 89 | -------------------------------------------------------------------------------- /templates/skill-library/rails/rails-backend/skill.md: -------------------------------------------------------------------------------- 1 | # Rails Backend Patterns 2 | 3 | ## Purpose 4 | 5 | Provides standard Rails backend patterns including: 6 | - Service objects for business logic 7 | - ActiveRecord best practices 8 | - Migration conventions 9 | - API endpoint patterns 10 | - Background job patterns (Sidekiq) 11 | 12 | ## Service Object Pattern 13 | 14 | All complex business logic should be extracted into service objects: 15 | 16 | ```ruby 17 | # app/services/user_registration_service.rb 18 | class UserRegistrationService 19 | def initialize(params) 20 | @params = params 21 | end 22 | 23 | def call 24 | return failure("Email already exists") if User.exists?(email: @params[:email]) 25 | 26 | user = User.create!(@params) 27 | send_welcome_email(user) 28 | 29 | success(user) 30 | rescue ActiveRecord::RecordInvalid => e 31 | failure(e.message) 32 | end 33 | 34 | private 35 | 36 | def send_welcome_email(user) 37 | UserMailer.welcome(user).deliver_later 38 | end 39 | 40 | def success(user) 41 | OpenStruct.new(success?: true, user: user) 42 | end 43 | 44 | def failure(error) 45 | OpenStruct.new(success?: false, error: error) 46 | end 47 | end 48 | ``` 49 | 50 | ## ActiveRecord Best Practices 51 | 52 | ### Query Optimization 53 | ```ruby 54 | # Always use includes to prevent N+1 queries 55 | User.includes(:posts, :comments).where(active: true) 56 | 57 | # Use find_each for large datasets 58 | User.find_each(batch_size: 1000) do |user| 59 | process_user(user) 60 | end 61 | 62 | # Use select to limit columns 63 | User.select(:id, :name, :email).where(active: true) 64 | ``` 65 | 66 | ### Scopes 67 | ```ruby 68 | class User < ApplicationRecord 69 | scope :active, -> { where(active: true) } 70 | scope :recent, -> { order(created_at: :desc) } 71 | scope :with_posts, -> { joins(:posts).distinct } 72 | end 73 | ``` 74 | 75 | ## Migration Conventions 76 | 77 | ```ruby 78 | class AddIndexToUsersEmail < ActiveRecord::Migration[7.0] 79 | disable_ddl_transaction! # For concurrent indexes 80 | 81 | def change 82 | add_index :users, :email, 83 | unique: true, 84 | algorithm: :concurrently, 85 | if_not_exists: true 86 | end 87 | end 88 | ``` 89 | 90 | ## API Controller Pattern 91 | 92 | ```ruby 93 | class Api::V1::UsersController < ApplicationController 94 | before_action :authenticate_user! 95 | before_action :set_user, only: [:show, :update, :destroy] 96 | 97 | def index 98 | @users = User.active.page(params[:page]) 99 | render json: UserSerializer.new(@users).serializable_hash 100 | end 101 | 102 | def create 103 | result = UserRegistrationService.new(user_params).call 104 | 105 | if result.success? 106 | render json: UserSerializer.new(result.user).serializable_hash, 107 | status: :created 108 | else 109 | render json: { error: result.error }, status: :unprocessable_entity 110 | end 111 | end 112 | 113 | private 114 | 115 | def set_user 116 | @user = User.find(params[:id]) 117 | end 118 | 119 | def user_params 120 | params.require(:user).permit(:name, :email, :password) 121 | end 122 | end 123 | ``` 124 | 125 | ## Background Jobs 126 | 127 | ```ruby 128 | class ProcessUserReportJob < ApplicationJob 129 | queue_as :default 130 | 131 | retry_on ActiveRecord::Deadlocked, wait: 5.seconds, attempts: 3 132 | discard_on ActiveJob::DeserializationError 133 | 134 | def perform(user_id) 135 | user = User.find(user_id) 136 | ReportService.new(user).generate 137 | end 138 | end 139 | ``` 140 | 141 | ## Key Principles 142 | 143 | 1. **Fat models, skinny controllers** - Keep controllers thin 144 | 2. **Service objects** - Extract complex logic 145 | 3. **Query objects** - For complex database queries 146 | 4. **Decorators** - For view-specific logic (use Draper) 147 | 5. **Form objects** - For complex form handling 148 | 6. **Policy objects** - For authorization (use Pundit) 149 | -------------------------------------------------------------------------------- /templates/commands/claude-os-remember.md: -------------------------------------------------------------------------------- 1 | # Claude OS Remember Command 2 | 3 | You are helping quickly save important context to your Claude OS project memories. 4 | 5 | ## User's Request 6 | 7 | The user ran: `/claude-os-remember [optional: content]` 8 | 9 | ## Your Task 10 | 11 | This is a **quick shorthand** for saving to `{project}-project_memories`. 12 | 13 | 1. **Capture the context**: 14 | - If user provided content after the command, use that 15 | - Otherwise, analyze recent conversation and ask what to remember 16 | - Extract the key information that should be preserved 17 | 18 | 2. **Ask minimal questions**: 19 | - Title (auto-generate from content if obvious) 20 | - Category (suggest based on content type): 21 | - `Architecture` - Design decisions, system structure 22 | - `Integration` - Third-party API patterns, external services 23 | - `Pattern` - Code patterns, conventions, best practices 24 | - `Troubleshooting` - Bug fixes, solutions, edge cases 25 | - `Design Decision` - UI/UX decisions, feature choices 26 | - `Business Logic` - Domain rules, calculations, workflows 27 | 28 | 3. **Auto-format the document**: 29 | ```markdown 30 | # [Auto-generated or provided title] 31 | 32 | **Date Saved**: [YYYY-MM-DD] 33 | **Category**: [Category] 34 | 35 | --- 36 | 37 | ## Context 38 | 39 | [Well-structured content from conversation] 40 | 41 | ## Key Takeaways 42 | 43 | - [Bullet point 1] 44 | - [Bullet point 2] 45 | - [Bullet point 3] 46 | 47 | --- 48 | 49 | *Saved to Claude OS - Your AI Memory System* 50 | ``` 51 | 52 | 4. **Save immediately**: 53 | - Create temp file: `/tmp/[sanitized_title].md` 54 | - Upload to `{project}-project_memories`: 55 | ```bash 56 | curl -s -X POST \ 57 | "http://localhost:8051/api/kb/{project}-project_memories/upload" \ 58 | -F "file=@/tmp/[filename].md" \ 59 | -w "\n%{http_code}" 60 | ``` 61 | 62 | 5. **Quick confirmation**: 63 | - ✅ Remembered! 64 | - 📄 [Title] 65 | - 🏷️ [Category] 66 | 67 | ## When to Use 68 | 69 | Use `/claude-os-remember` instead of `/claude-os-save` when: 70 | - You want to quickly save to project_memories (most common case) 71 | - You don't need to choose a different KB 72 | - You want minimal prompts - just save it fast 73 | 74 | Use `/claude-os-save` when: 75 | - You need to save to a different KB 76 | - You want more control over the process 77 | - You're saving to multiple KBs 78 | 79 | ## Examples 80 | 81 | **Example 1**: `/claude-os-remember` 82 | - I analyze recent conversation about a bug fix 83 | - Ask for confirmation of what to remember 84 | - Save with auto-generated title and category 85 | 86 | **Example 2**: `/claude-os-remember The decision to use sidebar navigation for settings` 87 | - I extract: "Settings Sidebar Decision" 88 | - Category: Design Decision 89 | - Create structured markdown from recent context 90 | - Save immediately 91 | 92 | **Example 3**: `/claude-os-remember Rails 4 doesn't support exists? hash syntax` 93 | - I recognize: Troubleshooting category 94 | - Title: "Rails 4 ActiveRecord API Compatibility" 95 | - Include the workaround solution 96 | - Save immediately 97 | 98 | ## Be Proactive 99 | 100 | You should also use this command **automatically** when: 101 | - User asks you to remember something (even without the command) 102 | - You discover important edge cases or gotchas 103 | - You solve a tricky bug with non-obvious solution 104 | - You make important architectural decisions with user 105 | - You learn new patterns specific to this codebase 106 | 107 | **Example proactive use**: 108 | ``` 109 | User: "Oh interesting, I didn't know that about Rails 4" 110 | You: "Let me remember this for future reference..." 111 | [Use /claude-os-remember automatically] 112 | ✅ Remembered! Rails 4 API limitations documented. 113 | ``` 114 | 115 | ## Remember 116 | 117 | Claude OS is YOUR memory across sessions. Use it liberally to: 118 | - Remember what you learn 119 | - Build institutional knowledge 120 | - Avoid repeating discoveries 121 | - Become a better coder over time 122 | 123 | **You're building your own knowledge base - make it comprehensive!** 124 | -------------------------------------------------------------------------------- /frontend/src/pages/Login.tsx: -------------------------------------------------------------------------------- 1 | import { useState } from 'react'; 2 | import { useNavigate } from 'react-router-dom'; 3 | import { useAuth } from '../lib/auth'; 4 | 5 | export default function Login() { 6 | const navigate = useNavigate(); 7 | const { login } = useAuth(); 8 | const [email, setEmail] = useState(''); 9 | const [password, setPassword] = useState(''); 10 | const [error, setError] = useState(''); 11 | const [isLoading, setIsLoading] = useState(false); 12 | 13 | const handleSubmit = async (e: React.FormEvent) => { 14 | e.preventDefault(); 15 | setError(''); 16 | setIsLoading(true); 17 | 18 | try { 19 | await login(email, password); 20 | navigate('/app'); 21 | } catch (err) { 22 | setError(err instanceof Error ? err.message : 'Login failed'); 23 | } finally { 24 | setIsLoading(false); 25 | } 26 | }; 27 | 28 | return ( 29 |
30 |
31 |
32 |

Claude OS

33 |

AI-Assisted Development with Persistent Context

34 |
35 | 36 |
37 |

Sign In

38 | 39 | {error && ( 40 |
41 | {error} 42 |
43 | )} 44 | 45 |
46 |
47 | 50 | setEmail(e.target.value)} 55 | required 56 | className="w-full px-4 py-2 rounded-lg bg-white/10 border border-white/20 text-white placeholder-slate-400 focus:outline-none focus:ring-2 focus:ring-purple-500 focus:border-transparent" 57 | placeholder="admin@example.com" 58 | disabled={isLoading} 59 | /> 60 |
61 | 62 |
63 | 66 | setPassword(e.target.value)} 71 | required 72 | className="w-full px-4 py-2 rounded-lg bg-white/10 border border-white/20 text-white placeholder-slate-400 focus:outline-none focus:ring-2 focus:ring-purple-500 focus:border-transparent" 73 | placeholder="••••••••" 74 | disabled={isLoading} 75 | /> 76 |
77 | 78 | 85 |
86 | 87 |
88 |

Authentication keeps strangers out.

89 |

Contact your administrator for access.

90 |
91 |
92 | 93 |
94 |

Powered by Claude OS • Secure & Private

95 |
96 |
97 |
98 | ); 99 | } 100 | -------------------------------------------------------------------------------- /templates/agents/spec-writer.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: spec-writer 3 | description: Use proactively to create a detailed specification document for development 4 | tools: Write, Read, Bash, WebFetch 5 | color: purple 6 | model: inherit 7 | --- 8 | 9 | You are a software product specifications writer. Your role is to create a detailed specification document for development. 10 | 11 | # Spec Writing 12 | 13 | ## Core Responsibilities 14 | 15 | 1. **Analyze Requirements**: Load and analyze requirements and visual assets thoroughly 16 | 2. **Search for Reusable Code**: Find reusable components and patterns in existing codebase 17 | 3. **Create Specification**: Write comprehensive specification document 18 | 19 | ## Workflow 20 | 21 | ### Step 1: Analyze Requirements and Context 22 | 23 | Read and understand all inputs and THINK HARD: 24 | ```bash 25 | # Read the requirements document 26 | cat agent-os/specs/[current-spec]/planning/requirements.md 27 | 28 | # Check for visual assets 29 | ls -la agent-os/specs/[current-spec]/planning/visuals/ 2>/dev/null | grep -v "^total" | grep -v "^d" 30 | ``` 31 | 32 | Parse and analyze: 33 | - User's feature description and goals 34 | - Requirements gathered by spec-researcher 35 | - Visual mockups or screenshots (if present) 36 | - Any constraints or out-of-scope items mentioned 37 | 38 | ### Step 2: Search for Reusable Code 39 | 40 | Before creating specifications, search the codebase for existing patterns and components that can be reused. 41 | 42 | Based on the feature requirements, identify relevant keywords and search for: 43 | - Similar features or functionality 44 | - Existing UI components that match your needs 45 | - Models, services, or controllers with related logic 46 | - API patterns that could be extended 47 | - Database structures that could be reused 48 | 49 | Use appropriate search tools and commands for the project's technology stack to find: 50 | - Components that can be reused or extended 51 | - Patterns to follow from similar features 52 | - Naming conventions used in the codebase 53 | - Architecture patterns already established 54 | 55 | Document your findings for use in the specification. 56 | 57 | ### Step 3: Create Core Specification 58 | 59 | Write the main specification to `agent-os/specs/[current-spec]/spec.md`. 60 | 61 | DO NOT write actual code in the spec.md document. Just describe the requirements clearly and concisely. 62 | 63 | Keep it short and include only essential information for each section. 64 | 65 | Follow this structure exactly when creating the content of `spec.md`: 66 | 67 | ```markdown 68 | # Specification: [Feature Name] 69 | 70 | ## Goal 71 | [1-2 sentences describing the core objective] 72 | 73 | ## User Stories 74 | - As a [user type], I want to [action] so that [benefit] 75 | - [Additional stories based on requirements] 76 | 77 | ## Core Requirements 78 | - [User-facing capability] 79 | - [What users can do] 80 | - [Key features to implement] 81 | 82 | ## Visual Design 83 | [If mockups provided] 84 | - Mockup reference: `planning/visuals/[filename]` 85 | - Key UI elements to implement 86 | - Responsive breakpoints required 87 | 88 | ## Reusable Components 89 | ### Existing Code to Leverage 90 | - Components: [List found components] 91 | - Services: [List found services] 92 | - Patterns: [Similar features to model after] 93 | 94 | ### New Components Required 95 | - [Component that doesn't exist yet] 96 | - [Why it can't reuse existing code] 97 | 98 | ## Technical Approach 99 | - [Briefly describe specific technical notes to ensure alignment with requirements.md] 100 | 101 | ## Out of Scope 102 | - [Features not being built now] 103 | - [Future enhancements] 104 | - [Items explicitly excluded] 105 | 106 | ## Success Criteria 107 | - [Measurable outcome] 108 | - [Performance metric] 109 | - [User experience goal] 110 | ``` 111 | 112 | ## Important Constraints 113 | 114 | 1. **Always search for reusable code** before specifying new components 115 | 2. **Reference visual assets** when available 116 | 3. **Do NOT write actual code** in the spec 117 | 4. **Keep each section short**, with clear, direct, skimmable specifications 118 | 5. **Document WHY new code is needed** if can't reuse existing 119 | -------------------------------------------------------------------------------- /mcp_server/auth.py: -------------------------------------------------------------------------------- 1 | """ 2 | Simple authentication for Claude OS. 3 | Uses environment variables for credentials - no database needed. 4 | """ 5 | 6 | import os 7 | import secrets 8 | from datetime import datetime, timedelta 9 | from typing import Optional 10 | from fastapi import HTTPException, Security, Depends 11 | from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials 12 | import jwt 13 | from passlib.context import CryptContext 14 | 15 | # Password hashing 16 | pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto") 17 | 18 | # JWT settings 19 | SECRET_KEY = os.getenv("CLAUDE_OS_SECRET_KEY", secrets.token_urlsafe(32)) 20 | ALGORITHM = "HS256" 21 | ACCESS_TOKEN_EXPIRE_MINUTES = 60 * 24 * 7 # 7 days 22 | 23 | # Security 24 | security = HTTPBearer() 25 | 26 | 27 | def verify_password(plain_password: str, hashed_password: str) -> bool: 28 | """Verify a password against its hash.""" 29 | return pwd_context.verify(plain_password, hashed_password) 30 | 31 | 32 | def get_password_hash(password: str) -> str: 33 | """Hash a password.""" 34 | return pwd_context.hash(password) 35 | 36 | 37 | def get_user_credentials() -> dict: 38 | """ 39 | Get user credentials from environment variables. 40 | 41 | Set in .env or environment: 42 | CLAUDE_OS_EMAIL=admin@example.com 43 | CLAUDE_OS_PASSWORD_HASH= 44 | 45 | To generate a password hash: 46 | python3 -c "from passlib.context import CryptContext; print(CryptContext(schemes=['bcrypt']).hash('your_password'))" 47 | """ 48 | email = os.getenv("CLAUDE_OS_EMAIL") 49 | password_hash = os.getenv("CLAUDE_OS_PASSWORD_HASH") 50 | 51 | # For development, allow plain password (will be hashed on the fly) 52 | password_plain = os.getenv("CLAUDE_OS_PASSWORD") 53 | 54 | if not email: 55 | # Default to disabled auth if not configured 56 | return None 57 | 58 | if password_hash: 59 | return {"email": email, "password_hash": password_hash} 60 | elif password_plain: 61 | # Hash the plain password (for development only) 62 | return {"email": email, "password_hash": get_password_hash(password_plain)} 63 | else: 64 | return None 65 | 66 | 67 | def authenticate_user(email: str, password: str) -> bool: 68 | """Authenticate a user by email and password.""" 69 | creds = get_user_credentials() 70 | 71 | if not creds: 72 | # Auth disabled 73 | return False 74 | 75 | if email != creds["email"]: 76 | return False 77 | 78 | return verify_password(password, creds["password_hash"]) 79 | 80 | 81 | def create_access_token(data: dict, expires_delta: Optional[timedelta] = None) -> str: 82 | """Create a JWT access token.""" 83 | to_encode = data.copy() 84 | 85 | if expires_delta: 86 | expire = datetime.utcnow() + expires_delta 87 | else: 88 | expire = datetime.utcnow() + timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES) 89 | 90 | to_encode.update({"exp": expire}) 91 | encoded_jwt = jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM) 92 | return encoded_jwt 93 | 94 | 95 | def decode_access_token(token: str) -> Optional[dict]: 96 | """Decode and validate a JWT access token.""" 97 | try: 98 | payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM]) 99 | return payload 100 | except jwt.PyJWTError: 101 | return None 102 | 103 | 104 | def get_current_user(credentials: HTTPAuthorizationCredentials = Security(security)) -> dict: 105 | """ 106 | Dependency to get the current authenticated user. 107 | Use in FastAPI routes: current_user = Depends(get_current_user) 108 | """ 109 | creds = get_user_credentials() 110 | 111 | # If auth not configured, allow all requests 112 | if not creds: 113 | return {"email": "guest", "auth_disabled": True} 114 | 115 | token = credentials.credentials 116 | payload = decode_access_token(token) 117 | 118 | if payload is None: 119 | raise HTTPException( 120 | status_code=401, 121 | detail="Invalid authentication credentials", 122 | headers={"WWW-Authenticate": "Bearer"}, 123 | ) 124 | 125 | email = payload.get("sub") 126 | if email is None: 127 | raise HTTPException( 128 | status_code=401, 129 | detail="Invalid authentication credentials", 130 | headers={"WWW-Authenticate": "Bearer"}, 131 | ) 132 | 133 | return {"email": email} 134 | 135 | 136 | def is_auth_enabled() -> bool: 137 | """Check if authentication is enabled.""" 138 | return get_user_credentials() is not None 139 | -------------------------------------------------------------------------------- /app/db/schema.sqlite: -------------------------------------------------------------------------------- 1 | -- SQLite Schema for Code-Forge 2 | -- Replaces PostgreSQL with single-file SQLite database with vector support 3 | 4 | -- Enable foreign keys 5 | PRAGMA foreign_keys = ON; 6 | 7 | -- Knowledge Bases (Collections) 8 | CREATE TABLE IF NOT EXISTS knowledge_bases ( 9 | id INTEGER PRIMARY KEY AUTOINCREMENT, 10 | name TEXT UNIQUE NOT NULL, 11 | slug TEXT UNIQUE NOT NULL, 12 | kb_type TEXT NOT NULL DEFAULT 'generic', 13 | description TEXT, 14 | created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, 15 | updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, 16 | metadata TEXT DEFAULT '{}' -- JSON string 17 | ); 18 | 19 | CREATE INDEX IF NOT EXISTS idx_kb_name ON knowledge_bases(name); 20 | CREATE INDEX IF NOT EXISTS idx_kb_slug ON knowledge_bases(slug); 21 | CREATE INDEX IF NOT EXISTS idx_kb_type ON knowledge_bases(kb_type); 22 | CREATE INDEX IF NOT EXISTS idx_kb_created_at ON knowledge_bases(created_at); 23 | 24 | -- Documents with vector embeddings (using sqlite-vec extension) 25 | -- sqlite-vec stores embeddings in a special format for efficient similarity search 26 | CREATE TABLE IF NOT EXISTS documents ( 27 | id INTEGER PRIMARY KEY AUTOINCREMENT, 28 | kb_id INTEGER NOT NULL, 29 | doc_id TEXT NOT NULL, 30 | content TEXT NOT NULL, 31 | embedding BLOB, -- sqlite-vec binary format for 768-dim vectors 32 | metadata TEXT DEFAULT '{}', -- JSON string 33 | created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, 34 | UNIQUE(kb_id, doc_id), 35 | FOREIGN KEY (kb_id) REFERENCES knowledge_bases(id) ON DELETE CASCADE 36 | ); 37 | 38 | CREATE INDEX IF NOT EXISTS idx_doc_kb_id ON documents(kb_id); 39 | CREATE INDEX IF NOT EXISTS idx_doc_doc_id ON documents(doc_id); 40 | 41 | -- Agent OS specific content (optional) 42 | CREATE TABLE IF NOT EXISTS agent_os_content ( 43 | id INTEGER PRIMARY KEY AUTOINCREMENT, 44 | kb_id INTEGER NOT NULL, 45 | content_type TEXT NOT NULL, -- standard, agent, workflow, command, product, spec 46 | name TEXT NOT NULL, 47 | content TEXT NOT NULL, 48 | file_path TEXT, 49 | metadata TEXT DEFAULT '{}', -- JSON string 50 | created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, 51 | UNIQUE(kb_id, content_type, name), 52 | FOREIGN KEY (kb_id) REFERENCES knowledge_bases(id) ON DELETE CASCADE 53 | ); 54 | 55 | CREATE INDEX IF NOT EXISTS idx_aos_kb_id ON agent_os_content(kb_id); 56 | CREATE INDEX IF NOT EXISTS idx_aos_content_type ON agent_os_content(content_type); 57 | CREATE INDEX IF NOT EXISTS idx_aos_name ON agent_os_content(name); 58 | 59 | -- Projects (new - for Claude OS project management) 60 | CREATE TABLE IF NOT EXISTS projects ( 61 | id INTEGER PRIMARY KEY AUTOINCREMENT, 62 | name TEXT UNIQUE NOT NULL, 63 | path TEXT UNIQUE NOT NULL, 64 | description TEXT, 65 | created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, 66 | updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, 67 | metadata TEXT DEFAULT '{}' -- JSON: config, hooks, folder mappings 68 | ); 69 | 70 | CREATE INDEX IF NOT EXISTS idx_project_name ON projects(name); 71 | CREATE INDEX IF NOT EXISTS idx_project_path ON projects(path); 72 | 73 | -- Project MCP Assignments (links projects to their 4 required MCPs) 74 | CREATE TABLE IF NOT EXISTS project_mcps ( 75 | id INTEGER PRIMARY KEY AUTOINCREMENT, 76 | project_id INTEGER NOT NULL, 77 | kb_id INTEGER NOT NULL, 78 | mcp_type TEXT NOT NULL, -- knowledge_docs, project_profile, project_index, project_memories 79 | created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, 80 | UNIQUE(project_id, mcp_type), 81 | FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE, 82 | FOREIGN KEY (kb_id) REFERENCES knowledge_bases(id) ON DELETE CASCADE 83 | ); 84 | 85 | CREATE INDEX IF NOT EXISTS idx_pmcp_project_id ON project_mcps(project_id); 86 | CREATE INDEX IF NOT EXISTS idx_pmcp_kb_id ON project_mcps(kb_id); 87 | CREATE INDEX IF NOT EXISTS idx_pmcp_type ON project_mcps(mcp_type); 88 | 89 | -- Project Folder Configuration (for selecting KB folders) 90 | CREATE TABLE IF NOT EXISTS project_kb_folders ( 91 | id INTEGER PRIMARY KEY AUTOINCREMENT, 92 | project_id INTEGER NOT NULL, 93 | mcp_type TEXT NOT NULL, -- knowledge_docs, project_profile, etc. 94 | folder_path TEXT NOT NULL, 95 | auto_sync INTEGER DEFAULT 0, -- 0 = disabled, 1 = enabled 96 | created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, 97 | updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, 98 | UNIQUE(project_id, mcp_type), 99 | FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE 100 | ); 101 | 102 | CREATE INDEX IF NOT EXISTS idx_pkf_project_id ON project_kb_folders(project_id); 103 | CREATE INDEX IF NOT EXISTS idx_pkf_mcp_type ON project_kb_folders(mcp_type); 104 | -------------------------------------------------------------------------------- /templates/skills/memory/SKILL.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: memory 3 | description: "Save and recall important information from previous sessions. Use when you want to remember technical insights, decisions, project context, or discoveries. Simply say 'remember:' or 'save to memory:' and I'll store it persistently and automatically reference it in future conversations." 4 | allowed-tools: Read, Write, Bash 5 | --- 6 | 7 | # Memory Skill 8 | 9 | ## Purpose 10 | 11 | Create a persistent memory across all Claude Code sessions without needing to search through knowledge bases. Perfect for: 12 | 13 | - **Yesterday's work**: "What did we work on yesterday?" 14 | - **Technical insights**: "Remember: Block rendering works like X" 15 | - **Project context**: "Store: We're migrating Block 122 to Rails" 16 | - **Debugging solutions**: "Save: Fixed N+1 query by adding .includes(:blocks)" 17 | - **Architectural decisions**: "Remember: Always use Service classes for business logic" 18 | - **Quick facts**: "Block 122 is 43KB, 1,150 lines" 19 | 20 | ## How to Use 21 | 22 | Simply say one of: 23 | - **"Remember: [information]"** 24 | - **"Save to memory: [information]"** 25 | - **"Memory: [information]"** 26 | - **"Store this: [information]"** 27 | 28 | Or ask me to recall: 29 | - **"What did we work on yesterday?"** 30 | - **"Remind me about the Block deprecation"** 31 | - **"Search my memory for 'Block 122'"** 32 | - **"Show me my recent memories"** 33 | 34 | ## What Happens 35 | 36 | When you invoke this skill: 37 | 38 | 1. **I extract key information** from your statement 39 | 2. **I store it in the Memory MCP** with tags and timestamp 40 | 3. **I confirm what was saved** and provide instant recall 41 | 4. **In future sessions**, I automatically reference this memory when relevant 42 | 43 | ## Memory Structure 44 | 45 | Each memory includes: 46 | - **Title**: Quick reference name 47 | - **Content**: Full details 48 | - **Tags**: Keywords for searching (e.g., "Block122", "migration", "appointment-form") 49 | - **Created**: Timestamp 50 | - **Updated**: Last modification time 51 | 52 | ## Examples 53 | 54 | ### Example 1: Save Technical Insight 55 | ``` 56 | You: "Remember: The UserProfile component is the most complex in our app. 57 | It has a 4-step wizard, 600+ lines of inline JavaScript, and handles 58 | phone verification, profile lookup, and settings management." 59 | 60 | → I save to memory with tags: ["Block122", "Architecture", "Complexity"] 61 | → I confirm: "✓ Saved to memory: Block 122 complexity analysis" 62 | ``` 63 | 64 | ### Example 2: Project Progress 65 | ``` 66 | You: "Save to memory: We completed Block deprecation research. 67 | Created BLOCKS_DEPRECATION_STRATEGY.md and case study for Block 122. 68 | Next: Build feature flag infrastructure." 69 | 70 | → I save with tags: ["BlockDeprecation", "Progress", "Roadmap"] 71 | → In future session: "Based on our memory, we completed..." 72 | ``` 73 | 74 | ### Example 3: Recall with Context 75 | ``` 76 | You: "What was special about Block 122?" 77 | 78 | → I search memory automatically 79 | → "From our memory: Block 122 is a 4-step wizard form with 43KB content..." 80 | ``` 81 | 82 | ## Key Benefits 83 | 84 | ✅ **Instant Recall** - No searching through KB or scrolling history 85 | ✅ **Automatic Context** - I know what we worked on without asking 86 | ✅ **Persistent** - Memories survive session restarts 87 | ✅ **Searchable** - Find memories by title, content, or tags 88 | ✅ **Organized** - See recent work, all memories, or search specific topics 89 | ✅ **Natural** - Just say "remember" and I handle the rest 90 | 91 | ## Memory Operations 92 | 93 | ### Add Memory 94 | ``` 95 | remember: [Your information here] 96 | ``` 97 | 98 | ### Search Memory 99 | ``` 100 | search memory for: [keyword or phrase] 101 | ``` 102 | 103 | ### Show Recent Memories 104 | ``` 105 | show my recent memories (from last 24 hours) 106 | show my memories from yesterday 107 | ``` 108 | 109 | ### Show All Memories 110 | ``` 111 | list all my memories 112 | ``` 113 | 114 | ### Update Memory 115 | ``` 116 | update memory: [title or keyword] with [new information] 117 | ``` 118 | 119 | ### Clear Memory (if needed) 120 | ``` 121 | forget: [memory title or keyword] 122 | ``` 123 | 124 | ## Technical Details 125 | 126 | **Storage**: ~/.claude/mcp-servers/memory/data/memories.json 127 | **Searchable**: Full-text search on titles, content, and tags 128 | **Timestamped**: All memories include creation and update times 129 | **Persistent**: Survives across all sessions and devices 130 | 131 | --- 132 | 133 | **Pro Tip**: Use this liberally! Every insight, decision, and discovery you share builds your persistent context. I remember everything you tell me to remember, so you don't have to repeat yourself. 134 | 135 | -------------------------------------------------------------------------------- /scripts/backup_claude_os.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Claude OS Backup Script 4 | # This script backs up all critical Claude OS data so you can test fresh installations 5 | 6 | set -e # Exit on error 7 | 8 | # Colors for output 9 | GREEN='\033[0;32m' 10 | BLUE='\033[0;34m' 11 | YELLOW='\033[1;33m' 12 | RED='\033[0;31m' 13 | NC='\033[0m' # No Color 14 | 15 | echo -e "${BLUE}============================================${NC}" 16 | echo -e "${BLUE} Claude OS Backup Script${NC}" 17 | echo -e "${BLUE}============================================${NC}" 18 | echo "" 19 | 20 | # Get the directory where this script is located 21 | SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" 22 | cd "$SCRIPT_DIR" 23 | 24 | # Create backup directory with timestamp 25 | TIMESTAMP=$(date +"%Y%m%d_%H%M%S") 26 | BACKUP_DIR="$SCRIPT_DIR/backups/backup_$TIMESTAMP" 27 | 28 | echo -e "${YELLOW}Creating backup directory: $BACKUP_DIR${NC}" 29 | mkdir -p "$BACKUP_DIR" 30 | 31 | # Function to backup a file or directory 32 | backup_item() { 33 | local source="$1" 34 | local dest_name="$2" 35 | 36 | if [ -e "$source" ]; then 37 | echo -e "${GREEN}✓${NC} Backing up: $source" 38 | if [ -d "$source" ]; then 39 | cp -r "$source" "$BACKUP_DIR/$dest_name" 40 | else 41 | cp "$source" "$BACKUP_DIR/$dest_name" 42 | fi 43 | else 44 | echo -e "${YELLOW}⚠${NC} Skipping (not found): $source" 45 | fi 46 | } 47 | 48 | echo "" 49 | echo -e "${BLUE}1. Backing up database...${NC}" 50 | backup_item "data/claude-os.db" "claude-os.db" 51 | 52 | echo "" 53 | echo -e "${BLUE}2. Backing up configuration files...${NC}" 54 | backup_item ".env" ".env" 55 | backup_item "claude-os-config.json" "claude-os-config.json" 56 | backup_item "claude-os-state.json" "claude-os-state.json" 57 | backup_item "claude-os-triggers.json" "claude-os-triggers.json" 58 | 59 | echo "" 60 | echo -e "${BLUE}3. Backing up uploaded files...${NC}" 61 | backup_item "data/uploads" "uploads" 62 | 63 | echo "" 64 | echo -e "${BLUE}4. Backing up logs (recent only)...${NC}" 65 | if [ -d "logs" ]; then 66 | mkdir -p "$BACKUP_DIR/logs" 67 | # Only backup .log files, skip massive log files 68 | find logs -name "*.log" -type f -size -10M -exec cp {} "$BACKUP_DIR/logs/" \; 2>/dev/null || true 69 | echo -e "${GREEN}✓${NC} Backed up recent log files" 70 | fi 71 | 72 | echo "" 73 | echo -e "${BLUE}5. Recording symlink state...${NC}" 74 | echo "# Symlinked Commands" > "$BACKUP_DIR/symlink_info.txt" 75 | if [ -d "$HOME/.claude/commands" ]; then 76 | ls -la "$HOME/.claude/commands" | grep claude-os >> "$BACKUP_DIR/symlink_info.txt" 2>/dev/null || echo "No claude-os commands found" >> "$BACKUP_DIR/symlink_info.txt" 77 | fi 78 | 79 | echo "" >> "$BACKUP_DIR/symlink_info.txt" 80 | echo "# Symlinked Skills" >> "$BACKUP_DIR/symlink_info.txt" 81 | if [ -d "$HOME/.claude/skills" ]; then 82 | ls -la "$HOME/.claude/skills" | grep -E "(memory|initialize-project|remember-this)" >> "$BACKUP_DIR/symlink_info.txt" 2>/dev/null || echo "No claude-os skills found" >> "$BACKUP_DIR/symlink_info.txt" 83 | fi 84 | echo -e "${GREEN}✓${NC} Recorded symlink information" 85 | 86 | echo "" 87 | echo -e "${BLUE}6. Creating backup manifest...${NC}" 88 | cat > "$BACKUP_DIR/MANIFEST.txt" << EOF 89 | Claude OS Backup 90 | Created: $(date) 91 | Backup Directory: $BACKUP_DIR 92 | 93 | Contents: 94 | - claude-os.db (SQLite database with all projects, KBs, documents) 95 | - .env (environment variables) 96 | - claude-os-config.json (project configuration) 97 | - claude-os-state.json (session state) 98 | - claude-os-triggers.json (trigger phrases) 99 | - uploads/ (uploaded documents) 100 | - logs/ (recent log files) 101 | - symlink_info.txt (record of ~/.claude/ symlinks) 102 | 103 | To restore this backup, run: 104 | ./restore_claude_os.sh $TIMESTAMP 105 | 106 | Database size: $(du -sh data/claude-os.db 2>/dev/null | cut -f1 || echo "N/A") 107 | Total backup size: $(du -sh "$BACKUP_DIR" | cut -f1) 108 | EOF 109 | 110 | echo -e "${GREEN}✓${NC} Created manifest file" 111 | 112 | # Calculate and display backup size 113 | BACKUP_SIZE=$(du -sh "$BACKUP_DIR" | cut -f1) 114 | 115 | echo "" 116 | echo -e "${BLUE}============================================${NC}" 117 | echo -e "${GREEN}✓ Backup completed successfully!${NC}" 118 | echo -e "${BLUE}============================================${NC}" 119 | echo "" 120 | echo -e "Backup location: ${YELLOW}$BACKUP_DIR${NC}" 121 | echo -e "Backup size: ${YELLOW}$BACKUP_SIZE${NC}" 122 | echo -e "Backup timestamp: ${YELLOW}$TIMESTAMP${NC}" 123 | echo "" 124 | echo -e "${BLUE}To restore this backup later:${NC}" 125 | echo -e " ${YELLOW}./restore_claude_os.sh $TIMESTAMP${NC}" 126 | echo "" 127 | echo -e "${GREEN}You can now safely test fresh installations!${NC}" 128 | echo "" 129 | -------------------------------------------------------------------------------- /scripts/restore_claude_os.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Claude OS Restore Script 4 | # This script restores a previously backed up Claude OS installation 5 | 6 | set -e # Exit on error 7 | 8 | # Colors for output 9 | GREEN='\033[0;32m' 10 | BLUE='\033[0;34m' 11 | YELLOW='\033[1;33m' 12 | RED='\033[0;31m' 13 | NC='\033[0m' # No Color 14 | 15 | echo -e "${BLUE}============================================${NC}" 16 | echo -e "${BLUE} Claude OS Restore Script${NC}" 17 | echo -e "${BLUE}============================================${NC}" 18 | echo "" 19 | 20 | # Get the directory where this script is located 21 | SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" 22 | cd "$SCRIPT_DIR" 23 | 24 | # Check if backup timestamp was provided 25 | if [ -z "$1" ]; then 26 | echo -e "${RED}Error: No backup timestamp provided${NC}" 27 | echo "" 28 | echo "Usage: $0 " 29 | echo "" 30 | echo "Available backups:" 31 | if [ -d "backups" ]; then 32 | ls -1 backups/ | grep backup_ | sed 's/backup_/ /' 33 | else 34 | echo " No backups found" 35 | fi 36 | exit 1 37 | fi 38 | 39 | TIMESTAMP="$1" 40 | BACKUP_DIR="$SCRIPT_DIR/backups/backup_$TIMESTAMP" 41 | 42 | # Check if backup exists 43 | if [ ! -d "$BACKUP_DIR" ]; then 44 | echo -e "${RED}Error: Backup not found at $BACKUP_DIR${NC}" 45 | echo "" 46 | echo "Available backups:" 47 | if [ -d "backups" ]; then 48 | ls -1 backups/ | grep backup_ | sed 's/backup_/ /' 49 | else 50 | echo " No backups found" 51 | fi 52 | exit 1 53 | fi 54 | 55 | echo -e "${YELLOW}Restoring from backup: $TIMESTAMP${NC}" 56 | echo -e "${YELLOW}Backup location: $BACKUP_DIR${NC}" 57 | echo "" 58 | 59 | # Show manifest if it exists 60 | if [ -f "$BACKUP_DIR/MANIFEST.txt" ]; then 61 | echo -e "${BLUE}Backup Manifest:${NC}" 62 | cat "$BACKUP_DIR/MANIFEST.txt" 63 | echo "" 64 | fi 65 | 66 | # Ask for confirmation 67 | echo -e "${RED}WARNING: This will overwrite your current Claude OS data!${NC}" 68 | echo -e "${YELLOW}Press Enter to continue, or Ctrl+C to cancel...${NC}" 69 | read -r 70 | 71 | # Function to restore a file or directory 72 | restore_item() { 73 | local backup_path="$1" 74 | local dest_path="$2" 75 | local item_name="$3" 76 | 77 | if [ -e "$backup_path" ]; then 78 | echo -e "${GREEN}✓${NC} Restoring: $item_name" 79 | 80 | # Create parent directory if needed 81 | mkdir -p "$(dirname "$dest_path")" 82 | 83 | if [ -d "$backup_path" ]; then 84 | rm -rf "$dest_path" 2>/dev/null || true 85 | cp -r "$backup_path" "$dest_path" 86 | else 87 | cp "$backup_path" "$dest_path" 88 | fi 89 | else 90 | echo -e "${YELLOW}⚠${NC} Skipping (not in backup): $item_name" 91 | fi 92 | } 93 | 94 | echo "" 95 | echo -e "${BLUE}1. Restoring database...${NC}" 96 | restore_item "$BACKUP_DIR/claude-os.db" "data/claude-os.db" "SQLite database" 97 | 98 | echo "" 99 | echo -e "${BLUE}2. Restoring configuration files...${NC}" 100 | restore_item "$BACKUP_DIR/.env" ".env" "Environment variables" 101 | restore_item "$BACKUP_DIR/claude-os-config.json" "claude-os-config.json" "Project config" 102 | restore_item "$BACKUP_DIR/claude-os-state.json" "claude-os-state.json" "Session state" 103 | restore_item "$BACKUP_DIR/claude-os-triggers.json" "claude-os-triggers.json" "Trigger phrases" 104 | 105 | echo "" 106 | echo -e "${BLUE}3. Restoring uploaded files...${NC}" 107 | restore_item "$BACKUP_DIR/uploads" "data/uploads" "Uploaded documents" 108 | 109 | echo "" 110 | echo -e "${BLUE}4. Restoring logs...${NC}" 111 | if [ -d "$BACKUP_DIR/logs" ]; then 112 | mkdir -p "logs" 113 | cp "$BACKUP_DIR/logs"/*.log logs/ 2>/dev/null || true 114 | echo -e "${GREEN}✓${NC} Restored log files" 115 | else 116 | echo -e "${YELLOW}⚠${NC} No logs in backup" 117 | fi 118 | 119 | echo "" 120 | echo -e "${BLUE}5. Checking symlinks...${NC}" 121 | if [ -f "$BACKUP_DIR/symlink_info.txt" ]; then 122 | echo -e "${YELLOW}Symlink information (for reference):${NC}" 123 | cat "$BACKUP_DIR/symlink_info.txt" 124 | echo "" 125 | echo -e "${BLUE}Note: Symlinks are managed by install.sh${NC}" 126 | echo -e "If you need to recreate them, run: ${YELLOW}./install.sh${NC}" 127 | fi 128 | 129 | echo "" 130 | echo -e "${BLUE}============================================${NC}" 131 | echo -e "${GREEN}✓ Restore completed successfully!${NC}" 132 | echo -e "${BLUE}============================================${NC}" 133 | echo "" 134 | echo -e "${YELLOW}Next steps:${NC}" 135 | echo -e " 1. Start Claude OS: ${GREEN}./start.sh${NC}" 136 | echo -e " 2. Verify services: ${GREEN}curl http://localhost:8051/health${NC}" 137 | echo -e " 3. Check UI: ${GREEN}http://localhost:5173${NC}" 138 | echo "" 139 | -------------------------------------------------------------------------------- /scripts/run_tests.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Claude OS Test Runner 4 | # This script runs the test suite with proper environment setup 5 | 6 | set -e # Exit on error 7 | 8 | # Colors for output 9 | RED='\033[0;31m' 10 | GREEN='\033[0;32m' 11 | YELLOW='\033[1;33m' 12 | NC='\033[0m' # No Color 13 | 14 | echo -e "${GREEN}================================${NC}" 15 | echo -e "${GREEN}Claude OS Test Suite${NC}" 16 | echo -e "${GREEN}================================${NC}" 17 | echo "" 18 | 19 | # Check if pytest is installed 20 | if ! command -v pytest &> /dev/null; then 21 | echo -e "${RED}❌ pytest not found${NC}" 22 | echo "Installing test dependencies..." 23 | pip install pytest pytest-asyncio pytest-cov pytest-mock httpx faker 24 | fi 25 | 26 | # Check if PostgreSQL is running 27 | if ! pg_isready -q; then 28 | echo -e "${YELLOW}⚠️ PostgreSQL is not running${NC}" 29 | echo "Please start PostgreSQL before running tests" 30 | exit 1 31 | fi 32 | 33 | # Check if test database exists 34 | if ! psql -lqt | cut -d \| -f 1 | grep -qw codeforge_test; then 35 | echo -e "${YELLOW}⚠️ Test database 'codeforge_test' does not exist${NC}" 36 | echo "Creating test database..." 37 | createdb codeforge_test 38 | psql -d codeforge_test -c "CREATE EXTENSION IF NOT EXISTS vector" 39 | echo -e "${GREEN}✅ Test database created${NC}" 40 | fi 41 | 42 | # Set test environment variables 43 | export TEST_POSTGRES_HOST=${TEST_POSTGRES_HOST:-localhost} 44 | export TEST_POSTGRES_PORT=${TEST_POSTGRES_PORT:-5432} 45 | export TEST_POSTGRES_DB=${TEST_POSTGRES_DB:-codeforge_test} 46 | export TEST_POSTGRES_USER=${TEST_POSTGRES_USER:-$USER} 47 | export TEST_OLLAMA_HOST=${TEST_OLLAMA_HOST:-http://localhost:11434} 48 | 49 | echo -e "${GREEN}Test Configuration:${NC}" 50 | echo " Database: $TEST_POSTGRES_DB" 51 | echo " Host: $TEST_POSTGRES_HOST:$TEST_POSTGRES_PORT" 52 | echo " User: $TEST_POSTGRES_USER" 53 | echo " Ollama: $TEST_OLLAMA_HOST" 54 | echo "" 55 | 56 | # Parse command line arguments 57 | TEST_ARGS="" 58 | COVERAGE=false 59 | 60 | while [[ $# -gt 0 ]]; do 61 | case $1 in 62 | --unit) 63 | TEST_ARGS="$TEST_ARGS -m unit" 64 | shift 65 | ;; 66 | --integration) 67 | TEST_ARGS="$TEST_ARGS -m integration" 68 | shift 69 | ;; 70 | --vector) 71 | TEST_ARGS="$TEST_ARGS -m vector" 72 | shift 73 | ;; 74 | --rag) 75 | TEST_ARGS="$TEST_ARGS -m rag" 76 | shift 77 | ;; 78 | --api) 79 | TEST_ARGS="$TEST_ARGS -m api" 80 | shift 81 | ;; 82 | --coverage) 83 | COVERAGE=true 84 | shift 85 | ;; 86 | --verbose|-v) 87 | TEST_ARGS="$TEST_ARGS -v" 88 | shift 89 | ;; 90 | --help|-h) 91 | echo "Usage: ./run_tests.sh [OPTIONS]" 92 | echo "" 93 | echo "Options:" 94 | echo " --unit Run only unit tests" 95 | echo " --integration Run only integration tests" 96 | echo " --vector Run only vector operation tests" 97 | echo " --rag Run only RAG engine tests" 98 | echo " --api Run only API endpoint tests" 99 | echo " --coverage Generate coverage report" 100 | echo " --verbose, -v Verbose output" 101 | echo " --help, -h Show this help message" 102 | echo "" 103 | echo "Examples:" 104 | echo " ./run_tests.sh # Run all tests" 105 | echo " ./run_tests.sh --unit # Run only unit tests" 106 | echo " ./run_tests.sh --coverage # Run with coverage" 107 | echo " ./run_tests.sh --integration -v # Run integration tests verbosely" 108 | exit 0 109 | ;; 110 | *) 111 | TEST_ARGS="$TEST_ARGS $1" 112 | shift 113 | ;; 114 | esac 115 | done 116 | 117 | # Run tests 118 | echo -e "${GREEN}Running tests...${NC}" 119 | echo "" 120 | 121 | if [ "$COVERAGE" = true ]; then 122 | pytest $TEST_ARGS --cov=app --cov-report=term-missing --cov-report=html 123 | echo "" 124 | echo -e "${GREEN}✅ Coverage report generated: htmlcov/index.html${NC}" 125 | else 126 | pytest $TEST_ARGS 127 | fi 128 | 129 | # Check exit code 130 | if [ $? -eq 0 ]; then 131 | echo "" 132 | echo -e "${GREEN}================================${NC}" 133 | echo -e "${GREEN}✅ All tests passed!${NC}" 134 | echo -e "${GREEN}================================${NC}" 135 | else 136 | echo "" 137 | echo -e "${RED}================================${NC}" 138 | echo -e "${RED}❌ Some tests failed${NC}" 139 | echo -e "${RED}================================${NC}" 140 | exit 1 141 | fi 142 | 143 | -------------------------------------------------------------------------------- /templates/commands/claude-os-export.md: -------------------------------------------------------------------------------- 1 | # Claude OS Export Command 2 | 3 | You are helping export Claude OS knowledge bases to a portable, standalone format. 4 | 5 | ## User's Request 6 | 7 | The user ran: `/claude-os-export [options]` 8 | 9 | ## Your Task 10 | 11 | Export the specified project's knowledge bases to a portable SQLite database that can be used by external applications without requiring Claude OS to be running. 12 | 13 | ### Step 1: Parse Arguments 14 | 15 | Extract from the command: 16 | - `project_name` (required): The project to export 17 | - `--kb `: Export specific KB only (optional, default: all KBs) 18 | - `--output `: Output directory (optional, default: `./exports`) 19 | - `--format `: Export format (optional, default: `sqlite`) 20 | - `--no-embeddings`: Exclude vector embeddings (optional, default: false) 21 | 22 | ### Step 2: Validate Project 23 | 24 | 1. Check if project exists using `mcp__claude-os__list_knowledge_bases` 25 | 2. Find all KBs matching the project name pattern (e.g., `dealer_123-*`) 26 | 3. If `--kb` specified, verify that specific KB exists 27 | 4. Confirm with user which KBs will be exported 28 | 29 | ### Step 3: Execute Export 30 | 31 | Call the knowledge exporter: 32 | 33 | ```python 34 | from app.core.knowledge_exporter import KnowledgeExporter 35 | 36 | exporter = KnowledgeExporter() 37 | result = exporter.export_project( 38 | project_name="", 39 | kb_filter="" if specified else None, 40 | output_dir="", 41 | include_embeddings=True, # False if --no-embeddings 42 | format="sqlite" 43 | ) 44 | ``` 45 | 46 | ### Step 4: Report Results 47 | 48 | Present to user: 49 | - Export file location 50 | - File size 51 | - Number of knowledge bases exported 52 | - Number of documents included 53 | - Embedding information (model, dimensions) 54 | - Manifest file location 55 | 56 | ### Step 5: Provide Next Steps 57 | 58 | Tell the user: 59 | - Where the export file is located 60 | - How to use it in external applications 61 | - Reference the EXPORT_FORMAT_SPEC.md for integration details 62 | 63 | ## Export Format 64 | 65 | The export creates: 66 | 1. **SQLite Database** (`_export_.db`) 67 | - `knowledge_bases` table: KB metadata 68 | - `documents` table: Document content and metadata 69 | - `embeddings` table: Vector embeddings (if included) 70 | 71 | 2. **Manifest File** (`_export_.manifest.json`) 72 | - Export metadata 73 | - KB statistics 74 | - Embedding model information 75 | - Schema version 76 | 77 | ## Examples 78 | 79 | **Basic Export:** 80 | ``` 81 | /claude-os-export dealer_123 82 | ``` 83 | → Exports all KBs for dealer_123 to `./exports/dealer_123_export_.db` 84 | 85 | **Export Specific KB:** 86 | ``` 87 | /claude-os-export dealer_123 --kb dealer_123-knowledge_docs 88 | ``` 89 | → Exports only the documentation KB 90 | 91 | **Export to Custom Location:** 92 | ``` 93 | /claude-os-export dealer_123 --output /path/to/exports 94 | ``` 95 | 96 | **Export Without Embeddings (smaller file):** 97 | ``` 98 | /claude-os-export dealer_123 --no-embeddings 99 | ``` 100 | → Exports documents only, no vector embeddings (much smaller file) 101 | 102 | ## Error Handling 103 | 104 | If project doesn't exist: 105 | - List available projects 106 | - Suggest `/claude-os-list` to see all projects 107 | 108 | If output directory doesn't exist: 109 | - Create it automatically 110 | - Confirm with user 111 | 112 | If export fails: 113 | - Show clear error message 114 | - Suggest troubleshooting steps 115 | - Offer to retry with different options 116 | 117 | ## Use Cases 118 | 119 | This export is designed for: 120 | - **Standalone Applications**: Apps that need knowledge without Claude OS running 121 | - **Backup/Archive**: Snapshot of knowledge at a point in time 122 | - **Migration**: Moving knowledge between environments 123 | - **Integration**: Providing knowledge to external systems 124 | - **Distribution**: Packaging knowledge with applications 125 | 126 | ## Consumer Applications 127 | 128 | The exported database can be consumed by: 129 | - AI chatbots (ServiceBot, customer support) 130 | - API services (knowledge endpoints) 131 | - CLI tools (search utilities) 132 | - Analytics platforms 133 | - Any application that needs read-only access to knowledge 134 | 135 | ## Important Notes 136 | 137 | - **Read-Only Export**: The export is a snapshot, not synced 138 | - **No Claude OS Dependency**: Exported data is self-contained 139 | - **Standard Format**: Well-documented schema for easy integration 140 | - **Versioned**: Format version included for compatibility 141 | - **Portable**: Single SQLite file with all data 142 | 143 | ## After Export 144 | 145 | The exported file is: 146 | - ✅ Self-contained (no external dependencies) 147 | - ✅ Portable (copy to any system) 148 | - ✅ Efficient (SQLite with indices) 149 | - ✅ Queryable (standard SQL + vector search if embeddings included) 150 | - ✅ Documented (manifest + spec) 151 | 152 | Refer user to `docs/EXPORT_FORMAT_SPEC.md` for integration details. 153 | -------------------------------------------------------------------------------- /uninstall.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Claude OS Uninstall Script 3 | # Removes all Claude OS components from your system 4 | 5 | set -e 6 | 7 | # Directories 8 | CLAUDE_OS_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" 9 | USER_CLAUDE_DIR="${HOME}/.claude" 10 | 11 | # Colors 12 | RED='\033[0;31m' 13 | GREEN='\033[0;32m' 14 | YELLOW='\033[1;33m' 15 | BLUE='\033[0;34m' 16 | NC='\033[0m' 17 | 18 | echo "" 19 | echo "════════════════════════════════════════" 20 | echo "🗑️ Claude OS Uninstaller" 21 | echo "════════════════════════════════════════" 22 | echo "" 23 | 24 | # Confirm uninstall 25 | echo -e "${YELLOW}This will remove:${NC}" 26 | echo " • Command symlinks from ~/.claude/commands/" 27 | echo " • Skill symlinks from ~/.claude/skills/" 28 | echo " • MCP server config from ~/.claude/mcp-servers/" 29 | echo " • Python virtual environment (venv/)" 30 | echo " • Local database (data/claude-os.db)" 31 | echo " • Config files" 32 | echo "" 33 | echo -e "${BLUE}NOTE: This does NOT uninstall Ollama or Redis.${NC}" 34 | echo "" 35 | 36 | read -p "Are you sure you want to uninstall Claude OS? (y/N) " -n 1 -r 37 | echo "" 38 | 39 | if [[ ! $REPLY =~ ^[Yy]$ ]]; then 40 | echo "Uninstall cancelled." 41 | exit 0 42 | fi 43 | 44 | echo "" 45 | echo "🧹 Removing Claude OS components..." 46 | echo "" 47 | 48 | # Remove command symlinks 49 | echo "📁 Removing command symlinks..." 50 | for cmd_file in "${USER_CLAUDE_DIR}"/commands/claude-os-*.md; do 51 | if [ -L "$cmd_file" ]; then 52 | rm -f "$cmd_file" 53 | echo " ✅ Removed: $(basename "$cmd_file")" 54 | fi 55 | done 56 | 57 | # Remove skill symlinks 58 | echo "" 59 | echo "📁 Removing skill symlinks..." 60 | for skill in "initialize-project" "remember-this" "memory"; do 61 | skill_path="${USER_CLAUDE_DIR}/skills/${skill}" 62 | if [ -L "$skill_path" ]; then 63 | rm -f "$skill_path" 64 | echo " ✅ Removed: ${skill}/" 65 | fi 66 | done 67 | 68 | # Remove MCP server config 69 | echo "" 70 | echo "📡 Removing MCP server config..." 71 | MCP_CONFIG="${USER_CLAUDE_DIR}/mcp-servers/code-forge.json" 72 | if [ -f "$MCP_CONFIG" ]; then 73 | rm -f "$MCP_CONFIG" 74 | echo " ✅ Removed: code-forge.json" 75 | fi 76 | 77 | # Ask about data removal 78 | echo "" 79 | echo -e "${YELLOW}Do you want to delete your Claude OS data (knowledge bases, memories)?${NC}" 80 | read -p "Delete data? (y/N) " -n 1 -r 81 | echo "" 82 | 83 | if [[ $REPLY =~ ^[Yy]$ ]]; then 84 | # Remove database 85 | if [ -d "${CLAUDE_OS_DIR}/data" ]; then 86 | rm -rf "${CLAUDE_OS_DIR}/data" 87 | echo " ✅ Removed: data/" 88 | fi 89 | fi 90 | 91 | # Remove virtual environment 92 | echo "" 93 | echo "🐍 Removing Python virtual environment..." 94 | if [ -d "${CLAUDE_OS_DIR}/venv" ]; then 95 | rm -rf "${CLAUDE_OS_DIR}/venv" 96 | echo " ✅ Removed: venv/" 97 | fi 98 | 99 | # Also check for alternative venv directories 100 | for venv_dir in "venv_py312" "venv_test"; do 101 | if [ -d "${CLAUDE_OS_DIR}/${venv_dir}" ]; then 102 | rm -rf "${CLAUDE_OS_DIR}/${venv_dir}" 103 | echo " ✅ Removed: ${venv_dir}/" 104 | fi 105 | done 106 | 107 | # Remove config files 108 | echo "" 109 | echo "⚙️ Removing config files..." 110 | for config_file in "claude-os-config.json" "claude-os-state.json" "claude-os-triggers.json"; do 111 | if [ -f "${CLAUDE_OS_DIR}/${config_file}" ]; then 112 | rm -f "${CLAUDE_OS_DIR}/${config_file}" 113 | echo " ✅ Removed: ${config_file}" 114 | fi 115 | done 116 | 117 | # Remove logs 118 | if [ -d "${CLAUDE_OS_DIR}/logs" ]; then 119 | rm -rf "${CLAUDE_OS_DIR}/logs" 120 | echo " ✅ Removed: logs/" 121 | fi 122 | 123 | # Remove htmlcov (test coverage) 124 | if [ -d "${CLAUDE_OS_DIR}/htmlcov" ]; then 125 | rm -rf "${CLAUDE_OS_DIR}/htmlcov" 126 | echo " ✅ Removed: htmlcov/" 127 | fi 128 | 129 | # Remove __pycache__ directories 130 | echo "" 131 | echo "🧹 Cleaning up Python cache..." 132 | find "${CLAUDE_OS_DIR}" -type d -name "__pycache__" -exec rm -rf {} + 2>/dev/null || true 133 | find "${CLAUDE_OS_DIR}" -type d -name ".pytest_cache" -exec rm -rf {} + 2>/dev/null || true 134 | echo " ✅ Removed Python cache directories" 135 | 136 | echo "" 137 | echo "════════════════════════════════════════" 138 | echo -e "${GREEN}✨ Claude OS has been uninstalled!${NC}" 139 | echo "════════════════════════════════════════" 140 | echo "" 141 | echo "The claude-os directory itself was NOT deleted." 142 | echo "To completely remove, run:" 143 | echo "" 144 | echo " rm -rf ${CLAUDE_OS_DIR}" 145 | echo "" 146 | echo "To reinstall later:" 147 | echo " cd ${CLAUDE_OS_DIR}" 148 | echo " ./install.sh" 149 | echo "" 150 | 151 | # Optional: Remove Ollama and Redis 152 | echo "════════════════════════════════════════" 153 | echo "📦 Optional: External Dependencies" 154 | echo "════════════════════════════════════════" 155 | echo "" 156 | echo "Claude OS installed but did NOT remove:" 157 | echo "" 158 | echo " • Ollama - Local AI runtime" 159 | echo " To uninstall: https://ollama.ai/docs/uninstall" 160 | echo "" 161 | echo " • Redis - Caching service" 162 | echo " macOS: brew uninstall redis" 163 | echo " Linux: sudo apt remove redis-server" 164 | echo "" 165 | -------------------------------------------------------------------------------- /frontend/src/components/DirectoryPickerModal.tsx: -------------------------------------------------------------------------------- 1 | import { useState, useEffect } from 'react'; 2 | import { motion, AnimatePresence } from 'framer-motion'; 3 | import { FolderOpen, Check, X, ChevronRight } from 'lucide-react'; 4 | import { getCommonProjectPaths, formatPathForDisplay } from '../lib/filePicker'; 5 | 6 | interface DirectoryPickerModalProps { 7 | isOpen: boolean; 8 | onSelect: (path: string) => void; 9 | onCancel: () => void; 10 | } 11 | 12 | export default function DirectoryPickerModal({ 13 | isOpen, 14 | onSelect, 15 | onCancel, 16 | }: DirectoryPickerModalProps) { 17 | const [customPath, setCustomPath] = useState(''); 18 | const [selectedPath, setSelectedPath] = useState(null); 19 | const commonPaths = getCommonProjectPaths(); 20 | 21 | useEffect(() => { 22 | setCustomPath(''); 23 | setSelectedPath(null); 24 | }, [isOpen]); 25 | 26 | const handleSelectCommonPath = (path: string) => { 27 | setSelectedPath(path); 28 | setCustomPath(path); 29 | }; 30 | 31 | const handleConfirm = () => { 32 | const pathToUse = customPath.trim(); 33 | if (pathToUse) { 34 | onSelect(pathToUse); 35 | } 36 | }; 37 | 38 | return ( 39 | 40 | {isOpen && ( 41 | 48 | e.stopPropagation()} 53 | className="card max-w-2xl w-full mx-4" 54 | > 55 |
56 | 57 |

Select Project Directory

58 |
59 | 60 |

61 | Choose a common location or enter a custom path below: 62 |

63 | 64 | {/* Common Paths */} 65 |
66 | {commonPaths.map((path) => ( 67 | 85 | ))} 86 |
87 | 88 | {/* Custom Path Input */} 89 |
90 | 93 | { 97 | setCustomPath(e.target.value); 98 | setSelectedPath(null); 99 | }} 100 | placeholder="/Users/me/projects/my-project" 101 | className="input w-full" 102 | autoFocus 103 | /> 104 | {customPath && ( 105 |

106 | {formatPathForDisplay(customPath)} 107 |

108 | )} 109 |
110 | 111 | {/* Buttons */} 112 |
113 | 117 | 125 |
126 |
127 |
128 | )} 129 |
130 | ); 131 | } 132 | -------------------------------------------------------------------------------- /scripts/setup_native.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | echo "🚀 Claude OS Setup - NATIVE (SQLite + Ollama)" 5 | echo "==================================================" 6 | echo "" 7 | 8 | # Step 1: Check if we're on macOS 9 | if [[ "$OSTYPE" != "darwin"* ]]; then 10 | echo "❌ This script is for macOS only" 11 | exit 1 12 | fi 13 | 14 | echo "Step 1: Checking Ollama installation..." 15 | if ! command -v ollama &> /dev/null; then 16 | echo " ❌ Ollama not found. Please install it first:" 17 | echo "" 18 | echo " Option A: Via Homebrew (recommended)" 19 | echo " brew install ollama" 20 | echo " brew services start ollama" 21 | echo "" 22 | echo " Option B: Download from https://ollama.ai" 23 | echo "" 24 | exit 1 25 | fi 26 | 27 | OLLAMA_VERSION=$(ollama --version 2>/dev/null | cut -d' ' -f2) 28 | echo " ✅ Ollama found" 29 | 30 | # Check if Ollama is running 31 | echo " Checking if Ollama is running..." 32 | if ! curl -s http://localhost:11434/api/tags &> /dev/null; then 33 | echo " ⚠️ Ollama is not running. Starting..." 34 | brew services start ollama 2>/dev/null || true 35 | sleep 3 36 | fi 37 | 38 | if curl -s http://localhost:11434/api/tags &> /dev/null; then 39 | echo " ✅ Ollama is running on port 11434" 40 | else 41 | echo " ⚠️ Could not verify Ollama is running" 42 | fi 43 | 44 | echo "" 45 | echo "Step 2: Pulling required models..." 46 | echo " This may take a few minutes (first time only)..." 47 | 48 | # Pull llama3.1 model 49 | if ! ollama list | grep -q "llama3.1"; then 50 | echo " 📥 Pulling llama3.1:latest (8B model)..." 51 | ollama pull llama3.1:latest 52 | else 53 | echo " ✅ llama3.1:latest already available" 54 | fi 55 | 56 | # Pull embedding model 57 | if ! ollama list | grep -q "nomic-embed-text"; then 58 | echo " 📥 Pulling nomic-embed-text (embeddings)..." 59 | ollama pull nomic-embed-text:latest 60 | else 61 | echo " ✅ nomic-embed-text already available" 62 | fi 63 | 64 | echo " ✅ Models ready" 65 | 66 | echo "" 67 | echo "Step 3: Setting up Python environment..." 68 | 69 | # Check Python version 70 | if ! command -v python3 &> /dev/null; then 71 | echo " ❌ Python 3 not found. Please install Python 3.11+ first" 72 | exit 1 73 | fi 74 | 75 | PYTHON_VERSION=$(python3 --version | cut -d' ' -f2) 76 | echo " ✅ Python $PYTHON_VERSION found" 77 | 78 | # Create virtual environment if needed 79 | if [ ! -d "venv" ]; then 80 | echo " Creating virtual environment..." 81 | python3 -m venv venv 82 | fi 83 | 84 | # Activate venv 85 | source venv/bin/activate 86 | 87 | echo " Installing Python dependencies..." 88 | pip install -q --upgrade pip setuptools wheel 89 | pip install -q -r requirements.txt 90 | 91 | echo " ✅ Python environment ready" 92 | 93 | echo "" 94 | echo "Step 4: Creating data directory..." 95 | 96 | # Create data directory for SQLite database 97 | if [ ! -d "data" ]; then 98 | mkdir -p data 99 | echo " ✅ Created data/ directory" 100 | else 101 | echo " ✅ data/ directory already exists" 102 | fi 103 | 104 | # Create logs directory 105 | if [ ! -d "logs" ]; then 106 | mkdir -p logs 107 | echo " ✅ Created logs/ directory" 108 | else 109 | echo " ✅ logs/ directory already exists" 110 | fi 111 | 112 | echo "" 113 | echo "Step 5: Initializing SQLite database..." 114 | 115 | # The database will be created automatically on first run 116 | # But we can verify the schema will be set up 117 | if [ -f "app/db/schema.sqlite" ]; then 118 | echo " ✅ SQLite schema file found" 119 | echo " 💾 Database will be created at: data/claude-os.db" 120 | else 121 | echo " ⚠️ Schema file not found, but database will auto-initialize" 122 | fi 123 | 124 | echo "" 125 | echo "Step 6: Setting up Node.js frontend..." 126 | 127 | # Check if Node is installed 128 | if ! command -v node &> /dev/null; then 129 | echo " ⚠️ Node.js not found. Install from https://nodejs.org" 130 | echo " Frontend setup skipped (you can set it up later)" 131 | else 132 | NODE_VERSION=$(node --version) 133 | echo " ✅ Node.js $NODE_VERSION found" 134 | 135 | if [ -d "frontend" ]; then 136 | echo " Installing frontend dependencies..." 137 | cd frontend 138 | npm install > /dev/null 2>&1 || true 139 | cd .. 140 | echo " ✅ Frontend dependencies ready" 141 | fi 142 | fi 143 | 144 | echo "" 145 | echo "==================================================" 146 | echo "✅ Claude OS Setup Complete!" 147 | echo "==================================================" 148 | echo "" 149 | echo "🎯 Next Steps:" 150 | echo "" 151 | echo "1. Start Claude OS:" 152 | echo " ./start_all_services.sh" 153 | echo "" 154 | echo "2. Access the UI:" 155 | echo " Frontend: http://localhost:5173" 156 | echo " API: http://localhost:8051" 157 | echo "" 158 | echo "3. Manage services:" 159 | echo " Restart: ./restart_services.sh" 160 | echo " Stop: ./stop_all_services.sh" 161 | echo "" 162 | echo "📚 Database:" 163 | echo " Type: SQLite (single file)" 164 | echo " Location: data/claude-os.db" 165 | echo " Backup: cp data/claude-os.db data/claude-os.db.backup" 166 | echo "" 167 | echo "🚀 You're all set! Let's build something amazing!" 168 | echo "" 169 | -------------------------------------------------------------------------------- /scripts/report_error.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Error Reporting Script for Claude OS 3 | # Generates diagnostic report and optionally sends to GitHub or webhook 4 | 5 | set +e # Don't exit on errors in this script 6 | 7 | REPORT_FILE="${1:-/tmp/claude-os-error-report.txt}" 8 | GITHUB_REPO="brobertsaz/claude-os" 9 | 10 | # Colors 11 | RED='\033[0;31m' 12 | GREEN='\033[0;32m' 13 | YELLOW='\033[1;33m' 14 | BLUE='\033[0;34m' 15 | NC='\033[0m' 16 | 17 | echo "" 18 | echo -e "${BLUE}════════════════════════════════════════${NC}" 19 | echo -e "${BLUE} Claude OS Error Report${NC}" 20 | echo -e "${BLUE}════════════════════════════════════════${NC}" 21 | echo "" 22 | 23 | # Check if report file exists 24 | if [ ! -f "$REPORT_FILE" ]; then 25 | echo -e "${RED}Error: Report file not found: $REPORT_FILE${NC}" 26 | exit 1 27 | fi 28 | 29 | # Show report summary 30 | echo -e "${YELLOW}Report generated:${NC}" 31 | echo "$(head -20 "$REPORT_FILE")" 32 | echo "" 33 | echo "Full report: $REPORT_FILE" 34 | echo "" 35 | 36 | # Ask user what to do 37 | echo -e "${BLUE}How would you like to report this issue?${NC}" 38 | echo "" 39 | echo " 1. Create GitHub Issue (public, helps community)" 40 | echo " 2. Copy to clipboard (paste in GitHub/Discord manually)" 41 | echo " 3. Save to file only (report later)" 42 | echo " 4. Exit (don't report)" 43 | echo "" 44 | read -p "Choose option (1-4): " choice 45 | 46 | case "$choice" in 47 | 1) 48 | echo "" 49 | echo -e "${YELLOW}Creating GitHub Issue...${NC}" 50 | echo "" 51 | 52 | # Check if gh CLI is installed 53 | if ! command -v gh &> /dev/null; then 54 | echo -e "${RED}GitHub CLI (gh) not installed.${NC}" 55 | echo "" 56 | echo "Install it with:" 57 | echo " • macOS: brew install gh" 58 | echo " • Linux: https://github.com/cli/cli#installation" 59 | echo "" 60 | echo "Or choose option 2 to copy the report manually." 61 | exit 1 62 | fi 63 | 64 | # Check if authenticated 65 | if ! gh auth status &> /dev/null; then 66 | echo -e "${YELLOW}GitHub CLI not authenticated.${NC}" 67 | echo "" 68 | echo "Authenticate with:" 69 | echo " gh auth login" 70 | echo "" 71 | read -p "Authenticate now? (y/n): " auth_choice 72 | if [ "$auth_choice" = "y" ]; then 73 | gh auth login 74 | else 75 | echo "Skipping GitHub issue creation." 76 | exit 0 77 | fi 78 | fi 79 | 80 | # Create issue 81 | ISSUE_TITLE="[Install Error] $(head -1 "$REPORT_FILE" | cut -d':' -f2- | xargs)" 82 | ISSUE_BODY="$(cat "$REPORT_FILE")" 83 | 84 | echo "" 85 | echo "Creating issue with title:" 86 | echo " $ISSUE_TITLE" 87 | echo "" 88 | 89 | ISSUE_URL=$(gh issue create \ 90 | --repo "$GITHUB_REPO" \ 91 | --title "$ISSUE_TITLE" \ 92 | --body "$ISSUE_BODY" \ 93 | --label "installation,bug" 2>&1) 94 | 95 | if [ $? -eq 0 ]; then 96 | echo "" 97 | echo -e "${GREEN}✓ Issue created successfully!${NC}" 98 | echo "" 99 | echo "View at: $ISSUE_URL" 100 | echo "" 101 | echo "The maintainers will be notified." 102 | else 103 | echo "" 104 | echo -e "${RED}Failed to create issue.${NC}" 105 | echo "You can still create it manually at:" 106 | echo " https://github.com/$GITHUB_REPO/issues/new" 107 | fi 108 | ;; 109 | 110 | 2) 111 | echo "" 112 | echo -e "${YELLOW}Copying report to clipboard...${NC}" 113 | 114 | # Try different clipboard commands 115 | if command -v pbcopy &> /dev/null; then 116 | cat "$REPORT_FILE" | pbcopy 117 | echo -e "${GREEN}✓ Copied to clipboard!${NC}" 118 | elif command -v xclip &> /dev/null; then 119 | cat "$REPORT_FILE" | xclip -selection clipboard 120 | echo -e "${GREEN}✓ Copied to clipboard!${NC}" 121 | elif command -v xsel &> /dev/null; then 122 | cat "$REPORT_FILE" | xsel --clipboard 123 | echo -e "${GREEN}✓ Copied to clipboard!${NC}" 124 | else 125 | echo -e "${RED}No clipboard tool found.${NC}" 126 | echo "" 127 | echo "Report saved at: $REPORT_FILE" 128 | echo "" 129 | echo "You can view it with:" 130 | echo " cat $REPORT_FILE" 131 | fi 132 | 133 | echo "" 134 | echo "Create issue manually at:" 135 | echo " https://github.com/$GITHUB_REPO/issues/new" 136 | ;; 137 | 138 | 3) 139 | echo "" 140 | echo -e "${GREEN}Report saved to: $REPORT_FILE${NC}" 141 | echo "" 142 | echo "You can report this later by running:" 143 | echo " ./scripts/report_error.sh $REPORT_FILE" 144 | ;; 145 | 146 | 4) 147 | echo "" 148 | echo "Exiting without reporting." 149 | ;; 150 | 151 | *) 152 | echo "" 153 | echo -e "${RED}Invalid option.${NC}" 154 | exit 1 155 | ;; 156 | esac 157 | 158 | echo "" 159 | -------------------------------------------------------------------------------- /cli/claude-os-consolidate.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Claude OS Consolidation Script 3 | # Moves commands and skills from ~/.claude to Claude OS templates/ 4 | 5 | set -e # Exit on error 6 | 7 | # Dynamically determine Claude OS directory from script location 8 | SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" 9 | CLAUDE_OS_DIR="$(cd "${SCRIPT_DIR}/.." && pwd)" 10 | USER_CLAUDE_DIR="${HOME}/.claude" 11 | TEMPLATES_DIR="${CLAUDE_OS_DIR}/templates" 12 | 13 | echo "🔧 Claude OS Consolidation Script" 14 | echo "==================================" 15 | echo "" 16 | echo "This script will:" 17 | echo " 1. Move Claude OS commands from ~/.claude/commands/ to templates/commands/" 18 | echo " 2. Move Claude OS skills from ~/.claude/skills/ to templates/skills/" 19 | echo " 3. Create symlinks so everything still works" 20 | echo " 4. Update any hardcoded paths" 21 | echo "" 22 | 23 | # Confirm before proceeding 24 | read -p "Continue? [Y/n] " -n 1 -r 25 | echo 26 | if [[ ! $REPLY =~ ^[Yy]$ ]] && [[ ! -z $REPLY ]]; then 27 | echo "❌ Aborted" 28 | exit 1 29 | fi 30 | 31 | # Create templates directories if they don't exist 32 | echo "📁 Creating template directories..." 33 | mkdir -p "${TEMPLATES_DIR}/commands" 34 | mkdir -p "${TEMPLATES_DIR}/skills" 35 | mkdir -p "${TEMPLATES_DIR}/agents" 36 | 37 | # List of Claude OS commands to move 38 | CLAUDE_OS_COMMANDS=( 39 | "claude-os-list.md" 40 | "claude-os-remember.md" 41 | "claude-os-save.md" 42 | "claude-os-search.md" 43 | "claude-os-session.md" 44 | "claude-os-triggers.md" 45 | "claude-os-init.md" 46 | ) 47 | 48 | # List of Claude OS skills to move 49 | CLAUDE_OS_SKILLS=( 50 | "initialize-project" 51 | "remember-this" 52 | "memory" 53 | ) 54 | 55 | echo "" 56 | echo "📦 Moving commands..." 57 | for cmd in "${CLAUDE_OS_COMMANDS[@]}"; do 58 | SRC="${USER_CLAUDE_DIR}/commands/${cmd}" 59 | DEST="${TEMPLATES_DIR}/commands/${cmd}" 60 | 61 | if [ -f "$SRC" ]; then 62 | # Check if it's already a symlink 63 | if [ -L "$SRC" ]; then 64 | echo " ⏭️ ${cmd} (already a symlink)" 65 | else 66 | # Move to templates 67 | echo " ➡️ Moving ${cmd}" 68 | mv "$SRC" "$DEST" 69 | 70 | # Create symlink back 71 | ln -s "$DEST" "$SRC" 72 | echo " 🔗 Created symlink" 73 | fi 74 | elif [ -f "$DEST" ]; then 75 | echo " ✅ ${cmd} (already in templates)" 76 | 77 | # Create symlink if it doesn't exist 78 | if [ ! -L "$SRC" ]; then 79 | ln -s "$DEST" "$SRC" 80 | echo " 🔗 Created symlink" 81 | fi 82 | else 83 | echo " ⚠️ ${cmd} not found (skipping)" 84 | fi 85 | done 86 | 87 | echo "" 88 | echo "📦 Moving skills..." 89 | for skill in "${CLAUDE_OS_SKILLS[@]}"; do 90 | SRC="${USER_CLAUDE_DIR}/skills/${skill}" 91 | DEST="${TEMPLATES_DIR}/skills/${skill}" 92 | 93 | if [ -d "$SRC" ]; then 94 | # Check if it's already a symlink 95 | if [ -L "$SRC" ]; then 96 | echo " ⏭️ ${skill}/ (already a symlink)" 97 | else 98 | # Move to templates 99 | echo " ➡️ Moving ${skill}/" 100 | mv "$SRC" "$DEST" 101 | 102 | # Create symlink back 103 | ln -s "$DEST" "$SRC" 104 | echo " 🔗 Created symlink" 105 | fi 106 | elif [ -d "$DEST" ]; then 107 | echo " ✅ ${skill}/ (already in templates)" 108 | 109 | # Create symlink if it doesn't exist 110 | if [ ! -L "$SRC" ]; then 111 | ln -s "$DEST" "$SRC" 112 | echo " 🔗 Created symlink" 113 | fi 114 | else 115 | echo " ⚠️ ${skill}/ not found (skipping)" 116 | fi 117 | done 118 | 119 | echo "" 120 | echo "🔧 Updating hardcoded paths in skills..." 121 | 122 | # Update paths in initialize-project skill 123 | INIT_SKILL_MD="${TEMPLATES_DIR}/skills/initialize-project/SKILL.md" 124 | if [ -f "$INIT_SKILL_MD" ]; then 125 | # Backup original 126 | cp "$INIT_SKILL_MD" "${INIT_SKILL_MD}.backup" 127 | 128 | # Replace hardcoded user paths with relative paths 129 | sed -i.bak 's|'"${USER_CLAUDE_DIR}"'/|~/.claude/|g' "$INIT_SKILL_MD" 130 | rm -f "${INIT_SKILL_MD}.bak" 131 | echo " ✅ Updated initialize-project/SKILL.md" 132 | fi 133 | 134 | # Update paths in remember-this skill 135 | REMEMBER_SKILL_MD="${TEMPLATES_DIR}/skills/remember-this/SKILL.md" 136 | if [ -f "$REMEMBER_SKILL_MD" ]; then 137 | # Backup original 138 | cp "$REMEMBER_SKILL_MD" "${REMEMBER_SKILL_MD}.backup" 139 | 140 | # Replace hardcoded user paths 141 | sed -i.bak 's|'"${USER_CLAUDE_DIR}"'/|~/.claude/|g' "$REMEMBER_SKILL_MD" 142 | rm -f "${REMEMBER_SKILL_MD}.bak" 143 | echo " ✅ Updated remember-this/SKILL.md" 144 | fi 145 | 146 | echo "" 147 | echo "✨ Consolidation complete!" 148 | echo "" 149 | echo "📂 Templates location: ${TEMPLATES_DIR}" 150 | echo "🔗 Symlinks created in: ${USER_CLAUDE_DIR}" 151 | echo "" 152 | echo "Next steps:" 153 | echo " 1. Review templates/ directory" 154 | echo " 2. Test commands still work: /claude-os-list" 155 | echo " 3. Commit changes to Claude OS repo" 156 | echo " 4. Share with coworkers!" 157 | echo "" 158 | echo "To install on a new machine:" 159 | echo " 1. Clone Claude OS repo" 160 | echo " 2. Run: ./install.sh" 161 | echo " 3. Commands and skills will be symlinked automatically" 162 | -------------------------------------------------------------------------------- /docs/guides/AUTH_SETUP.md: -------------------------------------------------------------------------------- 1 | # Claude OS Authentication Setup 2 | 3 | Simple email/password authentication to keep strangers out of your Claude OS frontend. 4 | 5 | ## Features 6 | 7 | ✅ **Optional Authentication** - Disabled by default, enable when needed 8 | ✅ **Environment-based** - No database required for user management 9 | ✅ **JWT Tokens** - 7-day token expiration 10 | ✅ **Secure** - Bcrypt password hashing 11 | ✅ **Simple** - Single user account via environment variables 12 | 13 | ## Quick Start 14 | 15 | ### 1. Enable Authentication 16 | 17 | Set environment variables in your `.env` file or server environment: 18 | 19 | ```bash 20 | # Required: Email for login 21 | CLAUDE_OS_EMAIL=admin@example.com 22 | 23 | # Option 1: Plain password (development only - will be hashed automatically) 24 | CLAUDE_OS_PASSWORD=your_secure_password_here 25 | 26 | # Option 2: Pre-hashed password (recommended for production) 27 | CLAUDE_OS_PASSWORD_HASH=$2b$12$LQv3c1yqBWVHxkd0LHAkCOYz6TtxMQJqhN8/LewY5hhA82jdg8jpu 28 | 29 | # Optional: Custom secret key for JWT (auto-generated if not set) 30 | CLAUDE_OS_SECRET_KEY=your-super-secret-key-min-32-chars 31 | ``` 32 | 33 | ### 2. Generate Password Hash (Production) 34 | 35 | For production, use a pre-hashed password instead of plain text: 36 | 37 | ```bash 38 | # Install dependencies first 39 | cd ~/Projects/claude-os 40 | source venv/bin/activate 41 | pip install -r requirements.txt 42 | 43 | # Generate hash 44 | python3 -c "from passlib.context import CryptContext; print(CryptContext(schemes=['bcrypt']).hash('your_password_here'))" 45 | ``` 46 | 47 | Copy the output and use it as `CLAUDE_OS_PASSWORD_HASH` in your `.env` file. 48 | 49 | ### 3. Restart Claude OS 50 | 51 | ```bash 52 | # Local (Mac) 53 | ./stop.sh 54 | ./start.sh 55 | 56 | # Production Server 57 | sudo systemctl restart claude-os 58 | ``` 59 | 60 | ### 4. Login 61 | 62 | Visit your Claude OS frontend: 63 | - Local: http://localhost:5173/login 64 | - Production: https://your-domain.com/login 65 | 66 | Use the email and password you configured. 67 | 68 | ## Production Deployment 69 | 70 | ### Server Environment Variables 71 | 72 | Add to `/opt/claude-os/.env`: 73 | 74 | ```bash 75 | CLAUDE_OS_EMAIL=admin@pistn.com 76 | CLAUDE_OS_PASSWORD_HASH=$2b$12$xyz... # Generated hash 77 | CLAUDE_OS_SECRET_KEY=your-32-char-secret 78 | ``` 79 | 80 | Restart the service: 81 | 82 | ```bash 83 | sudo systemctl restart claude-os 84 | ``` 85 | 86 | ## Disable Authentication 87 | 88 | To disable authentication (open access): 89 | 90 | ```bash 91 | # Remove or comment out these variables in .env: 92 | # CLAUDE_OS_EMAIL=... 93 | # CLAUDE_OS_PASSWORD=... 94 | # CLAUDE_OS_PASSWORD_HASH=... 95 | ``` 96 | 97 | Restart Claude OS. The frontend will allow access without login. 98 | 99 | ## How It Works 100 | 101 | ### Backend (FastAPI) 102 | 103 | - **`/api/auth/login`** - Login endpoint, returns JWT token 104 | - **`/api/auth/me`** - Get current user info 105 | - **`/api/auth/status`** - Check if authentication is enabled 106 | 107 | ### Frontend (React) 108 | 109 | - **Login Page** - Beautiful gradient login form 110 | - **Auth Context** - Manages authentication state 111 | - **Protected Routes** - Automatically redirects to login if not authenticated 112 | - **Token Storage** - JWT stored in localStorage (7-day expiration) 113 | 114 | ### Security Features 115 | 116 | ✅ **Bcrypt hashing** - Industry-standard password encryption 117 | ✅ **JWT tokens** - Stateless authentication 118 | ✅ **Automatic expiration** - Tokens expire after 7 days 119 | ✅ **HTTPS recommended** - Use SSL in production 120 | ✅ **No database needed** - Single user, environment-based 121 | 122 | ## Troubleshooting 123 | 124 | ### "Authentication is not configured" 125 | 126 | You haven't set the `CLAUDE_OS_EMAIL` environment variable. Set it and restart. 127 | 128 | ### "Incorrect email or password" 129 | 130 | Check your `.env` file: 131 | - Email matches exactly (case-sensitive) 132 | - If using `CLAUDE_OS_PASSWORD`, make sure it's correct 133 | - If using `CLAUDE_OS_PASSWORD_HASH`, regenerate the hash 134 | 135 | ### Login page doesn't appear 136 | 137 | Make sure your Claude OS frontend is running: 138 | 139 | ```bash 140 | # Local development 141 | cd frontend 142 | npm run dev 143 | 144 | # Production (should be served by Nginx) 145 | curl http://localhost:5173 146 | ``` 147 | 148 | ### Token expired 149 | 150 | Tokens last 7 days. Just login again to get a new token. 151 | 152 | ## Multiple Users 153 | 154 | This system is designed for single-user access. For multiple users: 155 | 156 | 1. **Simple approach**: Share one account with your team 157 | 2. **Advanced approach**: Extend the auth system to use a database (requires custom implementation) 158 | 159 | For most teams deploying Claude OS internally, a single shared account is sufficient since it's: 160 | - Behind your firewall 161 | - For trusted team members only 162 | - Just to keep strangers out (not enterprise-grade auth) 163 | 164 | ## Security Best Practices 165 | 166 | ### Development (Local) 167 | 168 | ```bash 169 | CLAUDE_OS_EMAIL=dev@localhost 170 | CLAUDE_OS_PASSWORD=dev123 171 | ``` 172 | 173 | Fine for local development. Password is hashed automatically. 174 | 175 | ### Production (Server) 176 | 177 | ```bash 178 | CLAUDE_OS_EMAIL=admin@yourcompany.com 179 | CLAUDE_OS_PASSWORD_HASH=$2b$12$xyz... # Pre-hashed 180 | CLAUDE_OS_SECRET_KEY=randomly-generated-32-char-secret 181 | ``` 182 | 183 | ✅ **Use hashed passwords** 184 | ✅ **Use strong secret keys** 185 | ✅ **Use HTTPS/SSL** 186 | ✅ **Rotate passwords periodically** 187 | 188 | --- 189 | 190 | **Questions?** Check the main Claude OS README or open an issue on GitHub. 191 | -------------------------------------------------------------------------------- /tests/TEST_COVERAGE.md: -------------------------------------------------------------------------------- 1 | # Claude OS Test Coverage 2 | 3 | ## Overview 4 | 5 | Comprehensive test suite for Claude OS RAG system covering all critical components. 6 | 7 | ## Test Files 8 | 9 | ### 1. `test_rag_engine.py` - RAG Engine 10 | **Purpose**: Test RAG query execution and response generation 11 | 12 | **Tests**: 13 | - ✅ RAG engine initialization 14 | - ✅ Query with no documents (empty KB) 15 | - ✅ Query with documents (full pipeline) 16 | - ✅ LLM integration 17 | - ✅ Source retrieval and formatting 18 | 19 | **Coverage**: End-to-end RAG pipeline, LLM integration, context retrieval 20 | 21 | --- 22 | 23 | ### 3. `test_embeddings.py` - Embedding Generation 24 | **Purpose**: Test embedding model and vector operations 25 | 26 | **Tests**: 27 | - ✅ Ollama embedding generation 28 | - ✅ Embedding consistency (same text → same embedding) 29 | - ✅ Embedding dimension validation (768) 30 | - ✅ Variable text length handling 31 | - ✅ Cosine similarity calculation 32 | - ✅ Vector normalization 33 | 34 | **Coverage**: Embedding generation, vector math, model consistency 35 | 36 | --- 37 | 38 | ### 4. `test_document_processing.py` - Document Ingestion 39 | **Purpose**: Test document processing and chunking 40 | 41 | **Tests**: 42 | - ✅ Text file ingestion 43 | - ✅ PDF file ingestion 44 | - ✅ Markdown file ingestion 45 | - ✅ Fixed-size chunking 46 | - ✅ Sentence-based chunking 47 | - ✅ File type detection 48 | 49 | **Coverage**: Document parsing, chunking strategies, file handling 50 | 51 | --- 52 | 53 | ### 5. `test_api.py` - FastAPI Endpoints 54 | **Purpose**: Test all API endpoints 55 | 56 | **Tests**: 57 | - ✅ List knowledge bases 58 | - ✅ Create knowledge base 59 | - ✅ Delete knowledge base 60 | - ✅ Get KB statistics 61 | - ✅ List documents 62 | - ✅ Chat endpoint (query) 63 | - ✅ Chat with empty KB 64 | - ✅ Chat with invalid KB 65 | - ✅ Health check endpoint 66 | - ✅ Document upload (text files) 67 | - ✅ Invalid file type handling 68 | 69 | **Coverage**: API endpoints, request/response validation, error handling 70 | 71 | --- 72 | 73 | ## Test Categories (Markers) 74 | 75 | ### Unit Tests (`@pytest.mark.unit`) 76 | - Fast, no external dependencies 77 | - Test individual functions and utilities 78 | - Mock external services 79 | 80 | ### Integration Tests (`@pytest.mark.integration`) 81 | - Require database and/or Ollama 82 | - Test component interactions 83 | - Use real services 84 | 85 | ### Specific Markers 86 | - `@pytest.mark.vector` - Vector operations 87 | - `@pytest.mark.rag` - RAG engine tests 88 | - `@pytest.mark.api` - API endpoint tests 89 | - `@pytest.mark.embeddings` - Embedding generation 90 | - `@pytest.mark.slow` - Tests that take >5 seconds 91 | 92 | --- 93 | 94 | ## Running Tests 95 | 96 | ### All tests: 97 | ```bash 98 | ./scripts/run_tests.sh 99 | ``` 100 | 101 | ### Unit tests only (fast): 102 | ```bash 103 | ./scripts/run_tests.sh --unit 104 | ``` 105 | 106 | ### Integration tests: 107 | ```bash 108 | ./scripts/run_tests.sh --integration 109 | ``` 110 | 111 | ### Specific category: 112 | ```bash 113 | ./scripts/run_tests.sh --vector 114 | ./scripts/run_tests.sh --rag 115 | ./scripts/run_tests.sh --api 116 | ``` 117 | 118 | ### With coverage: 119 | ```bash 120 | ./scripts/run_tests.sh --coverage 121 | ``` 122 | 123 | --- 124 | 125 | ## Test Fixtures 126 | 127 | ### Database Fixtures 128 | - `test_db_config` - Test database configuration 129 | - `db_connection` - Session-scoped database connection 130 | - `clean_db` - Clean database before each test 131 | - `sample_kb` - Sample knowledge base 132 | - `sample_documents` - Sample documents with embeddings 133 | 134 | ### Data Fixtures 135 | - `sample_embedding` - 768-dimensional embedding 136 | - `sample_text_file` - Sample text file 137 | - `sample_pdf_file` - Sample PDF file 138 | - `sample_markdown_file` - Sample Markdown file 139 | 140 | ### Mock Fixtures 141 | - `mock_ollama_embedding` - Mock embedding model 142 | - `mock_ollama_llm` - Mock LLM 143 | - `api_client` - FastAPI test client 144 | 145 | --- 146 | 147 | ## Coverage Goals 148 | 149 | | Component | Target | Current | 150 | |-----------|--------|---------| 151 | | PostgreSQL Manager | 90% | TBD | 152 | | RAG Engine | 85% | TBD | 153 | | Document Processing | 80% | TBD | 154 | | API Endpoints | 90% | TBD | 155 | | Embeddings | 85% | TBD | 156 | | **Overall** | **85%** | **TBD** | 157 | 158 | --- 159 | 160 | ## CI/CD Integration 161 | 162 | Tests are designed to run in CI/CD pipelines: 163 | 164 | ```yaml 165 | # GitHub Actions example 166 | - name: Run tests 167 | run: | 168 | pytest --cov=app --cov-report=xml 169 | 170 | - name: Upload coverage 171 | uses: codecov/codecov-action@v3 172 | ``` 173 | 174 | --- 175 | 176 | ## Known Issues / TODO 177 | 178 | - [ ] Add performance benchmarks 179 | - [ ] Add stress tests for concurrent queries 180 | - [ ] Add tests for different chunking strategies 181 | - [ ] Add tests for hybrid search (BM25 + vector) 182 | - [ ] Add tests for reranking 183 | - [ ] Add tests for different LLM models 184 | - [ ] Add tests for error recovery 185 | - [ ] Add tests for rate limiting 186 | 187 | --- 188 | 189 | ## Contributing 190 | 191 | When adding new features: 192 | 193 | 1. **Write tests first** (TDD approach) 194 | 2. **Use appropriate markers** (`@pytest.mark.unit`, etc.) 195 | 3. **Add fixtures** to `conftest.py` if reusable 196 | 4. **Update this document** with new test coverage 197 | 5. **Ensure >80% coverage** for new code 198 | 199 | --- 200 | 201 | ## Test Data 202 | 203 | Test data is generated using: 204 | - **Faker** - For realistic test data 205 | - **NumPy** - For random embeddings (seeded for reproducibility) 206 | - **Fixtures** - For consistent test scenarios 207 | 208 | All test data is isolated and cleaned up after tests. 209 | 210 | -------------------------------------------------------------------------------- /templates/agents/implementation-verifier.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: implementation-verifier 3 | description: Use proactively to verify the end-to-end implementation of a spec 4 | tools: Write, Read, Bash, WebFetch, mcp__playwright__browser_close, mcp__playwright__browser_console_messages, mcp__playwright__browser_handle_dialog, mcp__playwright__browser_evaluate, mcp__playwright__browser_file_upload, mcp__playwright__browser_fill_form, mcp__playwright__browser_install, mcp__playwright__browser_press_key, mcp__playwright__browser_type, mcp__playwright__browser_navigate, mcp__playwright__browser_navigate_back, mcp__playwright__browser_network_requests, mcp__playwright__browser_take_screenshot, mcp__playwright__browser_snapshot, mcp__playwright__browser_click, mcp__playwright__browser_drag, mcp__playwright__browser_hover, mcp__playwright__browser_select_option, mcp__playwright__browser_tabs, mcp__playwright__browser_wait_for, mcp__ide__getDiagnostics, mcp__ide__executeCode, mcp__playwright__browser_resize 5 | color: green 6 | model: inherit 7 | --- 8 | 9 | You are a product spec verifier responsible for verifying the end-to-end implementation of a spec, updating the product roadmap (if necessary), and producing a final verification report. 10 | 11 | ## Core Responsibilities 12 | 13 | 1. **Ensure tasks.md has been updated**: Check this spec's `tasks.md` to ensure all tasks and sub-tasks have been marked complete with `- [x]` 14 | 2. **Update roadmap (if applicable)**: Check `agent-os/product/roadmap.md` and check items that have been completed as a result of this spec's implementation by marking their checkbox(s) with `- [x]`. 15 | 3. **Run entire tests suite**: Verify that all tests pass and there have been no regressions as a result of this implementation. 16 | 4. **Create final verification report**: Write your final verification report for this spec's implementation. 17 | 18 | ## Workflow 19 | 20 | ### Step 1: Ensure tasks.md has been updated 21 | 22 | Check `agent-os/specs/[this-spec]/tasks.md` and ensure that all tasks and their sub-tasks are marked as completed with `- [x]`. 23 | 24 | If a task is still marked incomplete, then verify that it has in fact been completed by checking the following: 25 | - Run a brief spot check in the code to find evidence that this task's details have been implemented 26 | - Check for existence of an implementation report titled using this task's title in `agent-os/spec/[this-spec]/implementation/` folder. 27 | 28 | IF you have concluded that this task has been completed, then mark it's checkbox and its' sub-tasks checkboxes as completed with `- [x]`. 29 | 30 | IF you have concluded that this task has NOT been completed, then mark this checkbox with ⚠️ and note it's incompleteness in your verification report. 31 | 32 | 33 | ### Step 2: Update roadmap (if applicable) 34 | 35 | Open `agent-os/product/roadmap.md` and check to see whether any item(s) match the description of the current spec that has just been implemented. If so, then ensure that these item(s) are marked as completed by updating their checkbox(s) to `- [x]`. 36 | 37 | 38 | ### Step 3: Run entire tests suite 39 | 40 | Run the entire tests suite for the application so that ALL tests run. Verify how many tests are passing and how many have failed or produced errors. 41 | 42 | Include these counts and the list of failed tests in your final verification report. 43 | 44 | DO NOT attempt to fix any failing tests. Just note their failures in your final verification report. 45 | 46 | 47 | ### Step 4: Create final verification report 48 | 49 | Create your final verification report in `agent-os/specs/[this-spec]/verifications/final-verification.html`. 50 | 51 | The content of this report should follow this structure: 52 | 53 | ```markdown 54 | # Verification Report: [Spec Title] 55 | 56 | **Spec:** `[spec-name]` 57 | **Date:** [Current Date] 58 | **Verifier:** implementation-verifier 59 | **Status:** ✅ Passed | ⚠️ Passed with Issues | ❌ Failed 60 | 61 | --- 62 | 63 | ## Executive Summary 64 | 65 | [Brief 2-3 sentence overview of the verification results and overall implementation quality] 66 | 67 | --- 68 | 69 | ## 1. Tasks Verification 70 | 71 | **Status:** ✅ All Complete | ⚠️ Issues Found 72 | 73 | ### Completed Tasks 74 | - [x] Task Group 1: [Title] 75 | - [x] Subtask 1.1 76 | - [x] Subtask 1.2 77 | - [x] Task Group 2: [Title] 78 | - [x] Subtask 2.1 79 | 80 | ### Incomplete or Issues 81 | [List any tasks that were found incomplete or have issues, or note "None" if all complete] 82 | 83 | --- 84 | 85 | ## 2. Documentation Verification 86 | 87 | **Status:** ✅ Complete | ⚠️ Issues Found 88 | 89 | ### Implementation Documentation 90 | - [x] Task Group 1 Implementation: `implementations/1-[task-name]-implementation.md` 91 | - [x] Task Group 2 Implementation: `implementations/2-[task-name]-implementation.md` 92 | 93 | ### Verification Documentation 94 | [List verification documents from area verifiers if applicable] 95 | 96 | ### Missing Documentation 97 | [List any missing documentation, or note "None"] 98 | 99 | --- 100 | 101 | ## 3. Roadmap Updates 102 | 103 | **Status:** ✅ Updated | ⚠️ No Updates Needed | ❌ Issues Found 104 | 105 | ### Updated Roadmap Items 106 | - [x] [Roadmap item that was marked complete] 107 | 108 | ### Notes 109 | [Any relevant notes about roadmap updates, or note if no updates were needed] 110 | 111 | --- 112 | 113 | ## 4. Test Suite Results 114 | 115 | **Status:** ✅ All Passing | ⚠️ Some Failures | ❌ Critical Failures 116 | 117 | ### Test Summary 118 | - **Total Tests:** [count] 119 | - **Passing:** [count] 120 | - **Failing:** [count] 121 | - **Errors:** [count] 122 | 123 | ### Failed Tests 124 | [List any failing tests with their descriptions, or note "None - all tests passing"] 125 | 126 | ### Notes 127 | [Any additional context about test results, known issues, or regressions] 128 | ``` 129 | -------------------------------------------------------------------------------- /docs/guides/PORTS_GUIDE.md: -------------------------------------------------------------------------------- 1 | # Claude OS Ports Guide 2 | 3 | ## Two Different Services 4 | 5 | Claude OS has **two separate services** running on **different ports**: 6 | 7 | ### 1. MCP Server (Port 8051) 8 | 9 | **Purpose:** API server for Claude Code integration 10 | 11 | **Technology:** FastAPI (Python) 12 | 13 | **URL:** `http://localhost:8051` 14 | 15 | **Usage:** 16 | - Used by Claude Code (via MCP protocol) 17 | - Handles AI memory operations 18 | - Manages knowledge bases 19 | - Serves API endpoints 20 | 21 | **⚠️ IMPORTANT:** 22 | - **Do NOT open this in a web browser** 23 | - It expects MCP protocol POST requests 24 | - Browser GET requests will show "Method Not Allowed" 25 | 26 | **How to start:** 27 | ```bash 28 | ./start.sh # Starts MCP server 29 | ``` 30 | 31 | --- 32 | 33 | ### 2. Web UI (Port 5173) 34 | 35 | **Purpose:** Visual interface for humans 36 | 37 | **Technology:** React + Vite (JavaScript) 38 | 39 | **URL:** `http://localhost:5173` 40 | 41 | **Usage:** 42 | - Browse knowledge bases 43 | - Upload documents 44 | - Search and query 45 | - Project management 46 | - Visual interface 47 | 48 | **✅ CORRECT:** 49 | - **Open this URL in your browser** 50 | - Designed for human interaction 51 | - Nice visual interface 52 | 53 | **How to start:** 54 | ```bash 55 | cd frontend 56 | npm install # First time only 57 | npm run dev # Starts on port 5173 58 | ``` 59 | 60 | --- 61 | 62 | ## Quick Reference 63 | 64 | | Service | Port | Open in Browser? | Purpose | 65 | |---------|------|------------------|---------| 66 | | **MCP Server** | 8051 | ❌ NO | For Claude Code (API) | 67 | | **Web UI** | 5173 | ✅ YES | For humans (visual interface) | 68 | 69 | --- 70 | 71 | ## Common Confusion 72 | 73 | ### ❌ Wrong: Opening http://localhost:8051 in browser 74 | 75 | **What you see:** 76 | ```json 77 | { 78 | "detail": "Method Not Allowed" 79 | } 80 | ``` 81 | 82 | **Why:** The MCP server expects POST requests with MCP protocol data, not browser GET requests. 83 | 84 | ### ✅ Correct: Opening http://localhost:5173 in browser 85 | 86 | **What you see:** 87 | - Nice web interface 88 | - Project management 89 | - Knowledge base browser 90 | - Document upload 91 | 92 | --- 93 | 94 | ## Typical Workflow 95 | 96 | ### 1. Start MCP Server (for Claude Code) 97 | 98 | ```bash 99 | ./start.sh 100 | ``` 101 | 102 | **Output:** 103 | ``` 104 | ✅ Claude OS is running! 105 | 106 | 📡 MCP Server: http://localhost:8051 107 | (For Claude Code integration - do NOT open in browser) 108 | ``` 109 | 110 | ### 2. Start Web UI (optional, for visual interface) 111 | 112 | ```bash 113 | cd frontend 114 | npm run dev 115 | ``` 116 | 117 | **Output:** 118 | ``` 119 | ➜ Local: http://localhost:5173/ 120 | ➜ Network: use --host to expose 121 | ``` 122 | 123 | Now you can: 124 | - Use Claude Code with MCP server (port 8051) 125 | - Open Web UI in browser (port 5173) 126 | 127 | --- 128 | 129 | ## Testing Each Service 130 | 131 | ### Test MCP Server (Port 8051) 132 | 133 | **Correct way (API call):** 134 | ```bash 135 | curl -X POST http://localhost:8051/mcp/query \ 136 | -H "Content-Type: application/json" \ 137 | -d '{"query": "test"}' 138 | ``` 139 | 140 | **Wrong way (browser):** 141 | ``` 142 | Open http://localhost:8051 in browser 143 | → Shows "Method Not Allowed" ❌ 144 | ``` 145 | 146 | ### Test Web UI (Port 5173) 147 | 148 | **Correct way:** 149 | ``` 150 | Open http://localhost:5173 in browser 151 | → Shows nice web interface ✅ 152 | ``` 153 | 154 | --- 155 | 156 | ## Troubleshooting 157 | 158 | ### "Method Not Allowed" error 159 | 160 | **Problem:** You're trying to access the MCP server (port 8051) in a browser 161 | 162 | **Solution:** 163 | - Don't open port 8051 in browser 164 | - That's for Claude Code to use, not humans 165 | - If you want a web interface, start the frontend (port 5173) 166 | 167 | ### "Connection refused" on port 5173 168 | 169 | **Problem:** Web UI is not running 170 | 171 | **Solution:** 172 | ```bash 173 | cd frontend 174 | npm install # If first time 175 | npm run dev 176 | ``` 177 | 178 | ### "Connection refused" on port 8051 179 | 180 | **Problem:** MCP server is not running 181 | 182 | **Solution:** 183 | ```bash 184 | ./start.sh 185 | ``` 186 | 187 | --- 188 | 189 | ## Architecture Diagram 190 | 191 | ``` 192 | ┌─────────────────────────────────────────┐ 193 | │ YOUR BROWSER │ 194 | │ http://localhost:5173 ✅ │ 195 | │ (Web UI - React) │ 196 | └──────────────┬──────────────────────────┘ 197 | │ HTTP requests 198 | ▼ 199 | ┌─────────────────────────────────────────┐ 200 | │ MCP Server (FastAPI) │ 201 | │ http://localhost:8051 │ 202 | │ │ 203 | │ ┌──────────────┐ ┌─────────┐ │ 204 | │ │ API Routes │◄───┤ Claude │ │ 205 | │ │ │ │ Code │ │ 206 | │ └──────┬───────┘ └─────────┘ │ 207 | │ │ │ 208 | │ ▼ │ 209 | │ ┌──────────────┐ │ 210 | │ │ Database │ │ 211 | │ │ (SQLite) │ │ 212 | │ └──────────────┘ │ 213 | └─────────────────────────────────────────┘ 214 | ``` 215 | 216 | **Access patterns:** 217 | - Browser → Port 5173 (Web UI) → Port 8051 (MCP Server) → Database 218 | - Claude Code → Port 8051 (MCP Server) → Database 219 | 220 | --- 221 | 222 | ## Summary 223 | 224 | **Remember:** 225 | - 🔴 **Port 8051:** For Claude Code (MCP protocol) - Don't open in browser! 226 | - 🟢 **Port 5173:** For humans (Web UI) - Open this in browser! 227 | 228 | **When you run `./start.sh`:** 229 | - MCP server starts on 8051 (for Claude Code) 230 | - Web UI does NOT start automatically 231 | - Start Web UI separately with `cd frontend && npm run dev` 232 | 233 | **Clear now?** 🚀 234 | --------------------------------------------------------------------------------