agentleFS
shorin-nikitashorin-nikita/lisa/CLAUDE.md

lisa

CLAUDE.md85 starsChanged 21 months agoApache-2.0View on GitHub

Self-hosted AI platform combining N8N automation, Supabase database, Ollama LLMs, Whisper speech recognition, and media processing in a unified Docker Compose stack. The project uses a unified Docker Compose architecture with two separate compose files merged under one project: Critical: Never use separate project names. All docker compose commands MUST use -p localai to maintain service connectivity. Ollama uses Docker Compose profiles to support different hardware: Each profile has a matching init container (ollama-pull-models) that auto-downloads gemma3:1b (компактная модель от…

  • Reads credentials

We split this CLAUDE.md into the rules it gives an agent

13 rules. About 0 are common, 1 is distinctive, and 12 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈1

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 12

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Very specific:

    Critical: Never use separate project names.

    line 24
  2. Very specific:

    Create timestamped backup tarball (.env, n8n/backup, neo4j/data, shared/)

    line 71
  3. Very specific:

    Stop all services with docker compose -p localai down

    line 72
  4. Very specific:

    Create shared/ directory with mode 777

    line 93
  5. Very specific:

    Stop existing containers: docker compose -p localai down

    line 95
  6. Very specific:

    Start Supabase stack: docker compose -p localai -f supabase/docker/docker-compose.yml up -d

    line 96
  7. Distinctive:

    Wait 30 seconds for Supabase initialization

    line 97
  8. Very specific:

    Start AI stack: docker compose -p localai --profile <profile> -f docker-compose.yml [-f docker-compose.override.<env>.yml] up -d

    line 98
  9. Very specific:

    Wait for PostgreSQL healthcheck to become healthy (max 120s)

    line 99
  10. Very specific:

    If N8N_HOSTNAME=n8n.example.com → HTTPS with Let's Encrypt cert

    line 255
  11. Very specific:

    If N8N_HOSTNAME=:8001 → HTTP on localhost:8001

    line 256
  12. Very specific:

    Check Caddy logs: docker logs caddy -f

    line 344
  13. Very specific:

    Use base model instead of medium/large on CPU

    line 351

≈ “Common” is an estimate: at least 1 in 5 of the 25,680 CLAUDE.md files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
CLAUDE.md

CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.


Л.И.С.А. — Локальная Интеллектуальная Система Автоматизации

Self-hosted AI platform combining N8N automation, Supabase database, Ollama LLMs, Whisper speech recognition, and media processing in a unified Docker Compose stack.

Core Architecture

Multi-Compose Stack Pattern

The project uses a unified Docker Compose architecture with two separate compose files merged under one project:

  1. Main stack (docker-compose.yml) — AI services (N8N, Ollama, Whisper, Qdrant, etc.)
  2. Supabase stack (supabase/docker/docker-compose.yml) — Full Supabase suite included via include: directive
  3. All services share:
    • Single Docker network: localai_default
    • Single project name: localai
    • Single .env file (copied to supabase/docker/.env by startup script)

Critical: Never use separate project names. All docker compose commands MUST use -p localai to maintain service connectivity.

GPU Profile System

Ollama uses Docker Compose profiles to support different hardware:

  • cpu → ollama-cpu service (no GPU acceleration)
  • gpu-nvidia → ollama-gpu service with NVIDIA device reservations
  • gpu-amd → ollama-gpu-amd service with ROCm image and /dev/kfd, /dev/dri devices

Each profile has a matching init container (ollama-pull-models) that auto-downloads gemma3:1b (компактная модель от Google, ~1GB) and nomic-embed-text models on first run.

Custom N8N Build

N8N uses a custom Dockerfile (n8n-ffmpeg/Dockerfile) that adds FFmpeg to the official image:

  • Base: n8nio/n8n:latest
  • Adds: FFmpeg + ffprobe via apk add
  • Purpose: Enable media processing in N8N Execute Command nodes

Important: This image must be rebuilt when N8N updates. Use docker compose -p localai build n8n to rebuild.

Development Commands

Installation

# First-time setup (interactive)
python3 CTAPT.py

This script:

  1. Detects GPU (NVIDIA/AMD/CPU)
  2. Validates domains and email for Let's Encrypt
  3. Generates all secrets (N8N encryption keys, Supabase JWT, database passwords)
  4. Creates .env file with configuration
  5. Configures UFW firewall (ports 22, 80, 443) — CRITICAL: SSH rule added BEFORE enabling firewall
  6. Calls start_services.py to launch stack

Update System

# Update to latest version
python3 O6HOBA.py

Update process:

  1. Detect current GPU profile and environment from .env
  2. Create timestamped backup tarball (.env, n8n/backup, neo4j/data, shared/)
  3. Stop all services with docker compose -p localai down
  4. Pull Git updates from main branch
  5. Calculate and update resource limits in .env based on detected CPU/RAM
  6. Pull new Docker images with docker compose pull --ignore-buildable
  7. Rebuild custom images (n8n-ffmpeg)
  8. Restart services via start_services.py

Manual Service Control

# Start with specific profile and environment
python3 start_services.py --profile cpu --environment public

# Options:
#   --profile: cpu | gpu-nvidia | gpu-amd | none
#   --environment: private | public

Startup sequence (start_services.py):

  1. Validate .env has required variables (POSTGRES_PASSWORD, N8N_ENCRYPTION_KEY, JWT_SECRET, N8N_RUNNERS_AUTH_TOKEN)
  2. Clone Supabase repo with sparse checkout (only docker/ directory) if missing
  3. Create shared/ directory with mode 777
  4. Copy .env → supabase/docker/.env
  5. Stop existing containers: docker compose -p localai down
  6. Start Supabase stack: docker compose -p localai -f supabase/docker/docker-compose.yml up -d
  7. Wait 30 seconds for Supabase initialization
  8. Start AI stack: docker compose -p localai --profile <profile> -f docker-compose.yml [-f docker-compose.override.<env>.yml] up -d
  9. Wait for PostgreSQL healthcheck to become healthy (max 120s)

Docker Compose Commands

# View all running containers
docker ps

# Logs for entire project
docker compose -p localai logs -f

# Logs for specific service
docker logs n8n -f
docker logs whisper -f
docker logs ollama -f

# Stop all services (preserves volumes/data)
docker compose -p localai down

# Stop and DELETE all data (destructive!)
docker compose -p localai down -v

# Rebuild specific service
docker compose -p localai build n8n
docker compose -p localai up -d n8n

# Resource monitoring
docker stats

# Important: ALWAYS use -p localai to target the correct project

Implementation Details

Environment Configuration

The .env file is generated by CTAPT.py and contains:

Generated secrets (via secrets module):

  • N8N_ENCRYPTION_KEY, N8N_USER_MANAGEMENT_JWT_SECRET (32-byte hex)
  • N8N_RUNNERS_AUTH_TOKEN (32-byte hex) — токен для Task Runners External Mode
  • POSTGRES_PASSWORD, DASHBOARD_PASSWORD (alphanumeric only, no special chars to avoid URL encoding issues)
  • SECRET_KEY_BASE, VAULT_ENC_KEY (for Supabase)
  • LOGFLARE_PUBLIC_ACCESS_TOKEN, LOGFLARE_PRIVATE_ACCESS_TOKEN

User-provided values:

Resource limits (auto-calculated by O6HOBA.py and start_services.py):

  • Format: {SERVICE}_CPU_LIMIT, {SERVICE}_MEM_LIMIT, {SERVICE}_CPU_RESERVE, {SERVICE}_MEM_RESERVE
  • N8N_HEAP_SIZE — Node.js heap size (75% от N8N_MEM_LIMIT), критично для предотвращения OOM
  • Allocation optimized for RAG workflows: Ollama 30%, N8N 22%, PostgreSQL 18%, Runners 8%, Qdrant 5%
  • Limits are recalculated on every update via O6HOBA.py to apply optimizations

Proxy settings (optional, for routing API requests via external proxy):

  • PROXY_ENABLED=true/false — Enable/disable Squid proxy
  • PROXY_IP, PROXY_PORT, PROXY_USER, PROXY_PASS — External proxy credentials

Squid Proxy Configuration

Optional proxy service for routing API requests (Anthropic, OpenAI, OpenRouter) through an external proxy. Useful for regions with API restrictions.

Input format during setup:

IP:PORT@USER:PASS

Example: 45.87.241.81:8000@eoJaVV:fs4nPg

Enter - to skip proxy configuration.

Architecture:

┌─────────┐  HTTP_PROXY  ┌─────────┐  cache_peer  ┌──────────────┐
│   n8n   │──────────────►│  squid  │──────────────►│ External     │
│         │              │  :3128  │              │ Proxy Server │
└─────────┘              └─────────┘              └──────────────┘

Routed domains:

  • .anthropic.com, .claude.ai — Anthropic/Claude API
  • .openai.com, .api.openai.com — OpenAI API
  • .openrouter.ai — OpenRouter API
  • .x.ai, api.x.ai — Grok (xAI) API
  • .googleapis.com, generativelanguage.googleapis.com — Google Gemini API

Files:

  • squid/squid.conf.template — Template with placeholders
  • squid/squid.conf — Generated config (auto-created from template)

Docker Compose profile: proxy — Squid service only starts when PROXY_ENABLED=true

Managing proxy:

  • During installation: CTAPT.py prompts for proxy input
  • During updates: O6HOBA.py allows changing/disabling proxy
  • Squid config is regenerated automatically when proxy settings change

Supabase Sparse Checkout

Supabase is cloned with Git sparse checkout to download only the docker/ directory (~200MB instead of 2GB):

git clone --filter=blob:none --no-checkout https://github.com/supabase/supabase.git
cd supabase
git sparse-checkout init --cone
git sparse-checkout set docker
git checkout master

The main compose file includes it via:

include:
  - ./supabase/docker/docker-compose.yml

N8N Auto-Import Pattern

N8N workflows/credentials are imported on first launch using a one-shot init container:

n8n-import:
  container_name: n8n-import
  entrypoint: /bin/sh
  command:
    - "-c"
    - "n8n import:credentials --separate --input=/backup/credentials && n8n import:workflow --separate --input=/backup/workflows"
  volumes:
    - ./n8n/backup:/backup

n8n:
  depends_on:
    n8n-import:
      condition: service_completed_successfully

The main N8N container waits for successful import completion before starting.

Shared Directory

The shared/ directory enables file exchange between containers:

  • N8N mounts it as /data/shared
  • Used for temporary media files during FFmpeg processing
  • Must have mode 777 for write access from all containers
  • Auto-created by CTAPT.py and start_services.py

Caddy Dual-Mode Routing

Caddy supports simultaneous domain and localhost access via environment variable syntax:

{$N8N_HOSTNAME}, :8001 {
    reverse_proxy n8n:5678
}
  • If N8N_HOSTNAME=n8n.example.com → HTTPS with Let's Encrypt cert
  • If N8N_HOSTNAME=:8001 → HTTP on localhost:8001
  • Both modes can coexist by listing both (domain AND port)

Service Internal URLs

Whisper (OpenAI-compatible speech-to-text):

  • URL: http://whisper:8000
  • Endpoint: POST /v1/audio/transcriptions
  • Body: multipart/form-data with file (binary) and model (tiny/base/small)
  • Recommended: base model for CPU (best speed/accuracy balance)

Other key services:

  • Ollama: http://ollama:11434
  • Qdrant: http://qdrant:6333
  • Supabase API: http://kong:8000 (via Kong gateway)
  • PostgreSQL (N8N): postgres:5432
  • PostgreSQL (Supabase): db:5432
  • N8N Task Broker: n8n:5679 (для подключения runners)

PostgreSQL Healthcheck Wait

start_services.py waits for PostgreSQL healthcheck before completing:

def wait_for_postgres_healthy(timeout=120):
    result = subprocess.run(
        ["docker", "inspect", "--format", "{{.State.Health.Status}}", "localai-postgres-1"],
        capture_output=True, text=True
    )
    return result.stdout.strip() == "healthy"

This prevents N8N connection failures during parallel startup.

Pre-built N8N Workflows

Located in n8n/backup/workflows/, auto-imported on first launch:

  • RAG L.I.S.A.json — Production-ready RAG система с автозагрузкой файлов:
    • File trigger на /data/shared — автоматическая индексация новых файлов
    • Поддержка CSV, Excel, TXT, PDF
    • pgvector для векторного поиска, SQL для табличных данных
    • Оптимизированные настройки: chunkSize=1000, chunkOverlap=100
  • Telegram Bot.json — Full-featured bot with voice transcription, image analysis, analytics commands
  • HTTP Handle.json — Webhook configuration helper
  • Конвертация WebM → OGG + Транскрибация.json — Media conversion with Whisper transcription
  • V1_Local_RAG_AI_Agent.json — Basic RAG with Ollama
  • V2_Local_Supabase_RAG_AI_Agent.json — RAG with Supabase vector store (pgvector)
  • V3_Local_Agentic_RAG_AI_Agent.json — Advanced agentic RAG

Common Issues

FFmpeg not found in N8N

Problem: ffmpeg: not found in Execute Command node

Solution: Rebuild the custom N8N image:

docker inspect n8n | grep n8n-ffmpeg  # Verify custom image is in use
docker compose -p localai build n8n
docker compose -p localai up -d n8n

PostgreSQL unhealthy

Problem: container localai-postgres-1 is unhealthy

Solution:

docker logs localai-postgres-1  # Check logs
grep POSTGRES_VERSION .env      # Verify version is 16
docker compose -p localai down -v && python3 CTAPT.py  # Nuclear option: wipe and reinstall

Permission denied in shared/

Problem: N8N cannot write to /data/shared

Solution: chmod 777 shared/ (auto-fixed by start_services.py)

HTTPS not working

Problem: ERR_SSL_PROTOCOL_ERROR on domain access

Checklist:

  1. .env has real email (not test@test.test)
  2. DNS A-records point to server IP
  3. Ports 80/443 open in firewall
  4. Check Caddy logs: docker logs caddy -f

Whisper crashes on large files

Problem: socket hang up or ECONNRESET during transcription

Solutions:

  • Use base model instead of medium/large on CPU
  • Split files into <25MB chunks
  • Increase container memory limits

Task Runners — External Mode (n8n 2.0+)

Начиная с n8n 2.0, Code ноды выполняются через Task Runners — отдельные процессы для изоляции и безопасности. Л.И.С.А. использует External Mode — рекомендуемый подход для production.

Архитектура:

┌─────────────┐      WebSocket      ┌──────────────┐
│     n8n     │◄──────:5679────────►│ n8n-runners  │
│  (broker)   │    AUTH_TOKEN       │  (JS+Python) │
└─────────────┘                     └──────────────┘

Поддерживаемые языки:

  • JavaScript — полная поддержка, встроенные модули
  • Python — native Python (не Pyodide), включён через N8N_NATIVE_PYTHON_RUNNER=true

Ключевые переменные:

  • N8N_RUNNERS_AUTH_TOKEN — секретный токен для связи n8n и runners (генерируется автоматически)
  • N8N_RUNNERS_MODE=external — использование отдельного контейнера
  • N8N_NATIVE_PYTHON_RUNNER=true — включение поддержки Python Code нод
  • N8N_RUNNERS_BROKER_LISTEN_ADDRESS=0.0.0.0 — брокер слушает на всех интерфейсах

Лимиты памяти для 8GB RAM (оптимизировано для RAG):

СервисRAMCPUHeapНазначение
Ollama2.5GB50%—LLM + embedding модели
N8N1.8GB30%1.3GBWorkflow engine, обработка файлов
PostgreSQL1.5GB25%—Supabase + pgvector
N8N Runners640MB15%—Code ноды (JS/Python)
Qdrant400MB10%—Векторы (резерв)

ВАЖНО: N8N_HEAP_SIZE должен быть ~75% от N8N_MEM_LIMIT. Если heap > limit контейнера, Docker убьёт процесс по OOM.

Проверка работы:

# Проверить что runners подключился
docker logs n8n 2>&1 | grep -i "runner"
# Должно быть: "Task broker ready" или "Runner connected"

# Проверить статус контейнера runners
docker ps | grep n8n-runners

RAG workflow падает при загрузке больших файлов

Problem: N8N или Ollama падает при загрузке документов в RAG L.I.S.A.

Причины и решения:

  1. N8N OOM (Out of Memory):
    • Проверьте логи: docker logs n8n --tail 100
    • Обновите систему для пересчёта лимитов: python3 O6HOBA.py
    • При обновлении автоматически настраивается N8N_HEAP_SIZE = 75% от N8N_MEM_LIMIT
  2. Ollama не справляется с эмбеддингами:
    • Workflow использует nomic-embed-text для векторизации
    • Большие файлы создают много чанков → много запросов к Ollama
    • Workflow оптимизирован: chunkSize=1000 (раньше было 300)
  3. PostgreSQL pgvector OOM:
    • HNSW индекс требует RAM при массовой вставке
    • Увеличьте лимит: в .env измените POSTGRES_MEM_LIMIT

Диагностика:

# Какой контейнер упал?
docker ps -a | grep -E "(Exited|OOM)"

# Проверить OOM killer
dmesg | grep -i "killed process"

# Мониторинг памяти в реальном времени
docker stats

Проблемы с Code нодами

Problem: Unknown error или JsTaskRunnerSandbox в Code нодах

Solution:

# 1. Проверьте что контейнер runners запущен
docker ps | grep n8n-runners

# 2. Проверьте логи runners
docker logs n8n-runners

# 3. Если runners не запускается — обновите систему
python3 O6HOBA.py

# 4. Или перезапустите вручную
docker compose -p localai down
python3 start_services.py --profile <your-profile> --environment <your-env>

Если миграция с Internal Mode: При обновлении с версии без External Mode, скрипт O6HOBA.py автоматически:

  1. Генерирует N8N_RUNNERS_AUTH_TOKEN
  2. Добавляет его в .env
  3. Запускает новый контейнер n8n-runners

Access Ports

External (via Caddy):

Internal (Docker network):

  • N8N: n8n:5678
  • N8N Task Broker: n8n:5679 (для n8n-runners)
  • N8N Runners: n8n-runners (без портов, подключается к broker)
  • Ollama: ollama:11434
  • Whisper: whisper:8000
  • Qdrant: qdrant:6333
  • PostgreSQL (N8N): postgres:5432
  • PostgreSQL (Supabase): db:5432
  • Kong (Supabase API): kong:8000
  • Squid Proxy: squid:3128 (только при PROXY_ENABLED=true)

Key Architectural Patterns

  1. Init Container Pattern: Used for N8N workflow import and Ollama model downloads
  2. Sparse Git Checkout: Supabase repo cloned with only docker/ directory to save bandwidth
  3. Healthcheck Dependencies: PostgreSQL healthcheck prevents race conditions during startup
  4. Dual-Environment Support: Same compose files work for private (localhost) and public (domain) deployments
  5. Resource Limits: Auto-calculated from system specs, stored in .env, applied via Docker deploy resources
  6. Custom Image Builds: N8N image extended with FFmpeg, requires manual rebuild on upstream updates
  7. Task Runners External Mode: Code nodes execute in separate n8n-runners container for isolation, security, and stability. Broker communicates on port 5679 via N8N_RUNNERS_AUTH_TOKEN
  8. Optional Proxy Profile: Squid proxy routes API requests through external proxy when PROXY_ENABLED=true. Uses Docker Compose proxy profile for conditional activation

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.