├── 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 |
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 |
--------------------------------------------------------------------------------