Markdown Converter
Agent skill for markdown-converter
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Sign in to like and favorite skills
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Trilium AI is a RAG (Retrieval Augmented Generation) system that enables semantic search and LLM integration with Trilium Notes. It reads from Trilium's SQLite database, indexes notes into Weaviate (vector database), and provides an LLM gateway for natural language queries.
# Install/sync dependencies uv sync # Install with dev dependencies uv sync --all-extras # Add a new dependency uv add <package-name> # Add a dev dependency uv add --dev <package-name> # Run a command in the virtual environment uv run <command>
# Run all tests uv run pytest # Run specific test file uv run pytest tests/test_indexer/test_sqlite_reader.py # Run with coverage uv run pytest --cov=src/trilium_ai --cov-report=html # Run specific test uv run pytest tests/test_indexer/test_sqlite_reader.py::test_read_notes
# Format code uv run black src/ tests/ # Check formatting uv run black --check src/ tests/ # Lint uv run ruff check src/ tests/ # Fix linting issues uv run ruff check --fix src/ tests/ # Type check uv run mypy src/
# Full index uv run trilium-ai index --full # Incremental sync uv run trilium-ai index --incremental # Watch mode uv run trilium-ai index --watch # Query uv run trilium-ai query "your question here" # Status check uv run trilium-ai status
# Start Weaviate cd docker && docker compose up -d # Stop Weaviate cd docker && docker compose down # View logs cd docker && docker compose logs -f
src/trilium_ai/ ├── indexer/ # Trilium Indexer Service │ ├── sqlite_reader.py # Reads from Trilium SQLite database │ ├── chunker.py # Splits notes into chunks │ ├── embedder.py # Generates vector embeddings │ └── sync.py # Manages incremental sync with Weaviate │ ├── gateway/ # LLM Gateway │ ├── retriever.py # Retrieves relevant chunks from Weaviate │ ├── prompt.py # Assembles prompts with context │ └── llm_client.py # Calls OpenAI/Anthropic APIs │ ├── shared/ # Shared utilities │ ├── weaviate_client.py # Weaviate connection and operations │ ├── config.py # Configuration management │ └── models.py # Pydantic models for data validation │ └── cli/ # CLI interface └── commands.py # Click commands for user interaction
Trilium uses SQLite with the following key tables:
notes tablenoteId (TEXT, PRIMARY KEY): Unique note identifiertitle (TEXT): Note titletype (TEXT): Note type (text, code, image, etc.)mime (TEXT): MIME typeblobId (TEXT): Foreign key to blobs table (content storage)isDeleted (INTEGER): Soft delete flagdateCreated (TEXT): Creation timestampdateModified (TEXT): Last modification timestamputcDateModified (TEXT): UTC modification timestamp (for sync tracking)blobs tableblobId (TEXT, PRIMARY KEY): Unique blob identifiercontent (TEXT): Note content (text or binary)dateModified (TEXT): Modification timestamputcDateModified (TEXT): UTC modification timestampbranches tablebranchId (TEXT, PRIMARY KEY): Unique branch identifiernoteId (TEXT): Foreign key to notesparentNoteId (TEXT): Parent note ID (tree structure)notePosition (INTEGER): Position in parent's childrenisExpanded (INTEGER): UI expansion stateisDeleted (INTEGER): Soft delete flagattributes tableattributeId (TEXT, PRIMARY KEY): Unique attribute identifiernoteId (TEXT): Foreign key to notestype (TEXT): "label" or "relation"name (TEXT): Attribute namevalue (TEXT): Attribute value (for labels)isDeleted (INTEGER): Soft delete flagisDeleted = 0branches table to navigate note treeutcDateModified for incremental updatesnotes with blobs on blobIdConfiguration is loaded from YAML files using Pydantic Settings. Environment variables override config file values:
from trilium_ai.shared.config import get_config config = get_config() db_path = config.trilium.database_path
The system uses a shared Weaviate client for all operations:
from trilium_ai.shared.weaviate_client import get_weaviate_client client = get_weaviate_client() collection = client.collections.get(config.weaviate.collection_name)
utcDateModified > last_sync_timeNotes are chunked to fit within embedding model token limits:
max_chunk_size tokenschunk_overlap tokens for context continuityEmbeddings are generated per chunk:
text-embedding-3-small or text-embedding-3-largeHybrid search combines vector and keyword search:
alpha parameter controls vector vs keyword weight (0-1)min_score thresholdContext is assembled from retrieved chunks:
System: You are an AI assistant with access to the user's Trilium notes. Context from notes: [Note: {title}] {chunk_content} [Note: {title}] {chunk_content} User: {query}
Response includes source citations (noteId, title) for transparency.
class Note: note_id: str title: str type: str content: str attributes: List[Attribute] utc_date_modified: datetime
class Chunk: chunk_id: str # {noteId}_{chunk_index} note_id: str title: str content: str chunk_index: int metadata: Dict[str, Any] # tags, labels, path
class SearchResult: chunks: List[Chunk] scores: List[float] total_results: int
docker compose ps)top_k based on query complexity# tests/fixtures/trilium_db.py @pytest.fixture def test_trilium_db(): # Create temporary SQLite with sample notes pass # tests/fixtures/weaviate.py @pytest.fixture def test_weaviate(): # Create test collection pass
.env or config.yaml with real keysTrilium is running and has the database locked. Either:
Collection schema doesn't match configuration. Reset:
uv run trilium-ai reset
Reduce batch size in config:
weaviate: batch_size: 50 # reduce from 100
top_k for more contextalpha (0.5 = balanced, 0.75 = more semantic)