Instruction file imported from DataCovey/nornweave (
.cursor/rules/main.mdc). Copyright stays with the author.
NornWeave - Cursor Rules
NornWeave is an open-source, self-hosted Inbox-as-a-Service API for AI Agents. It provides a stateful email layer (Inboxes, Threads, History) and an intelligent layer (Markdown parsing, Semantic Search) for LLMs via REST or MCP.
Repository Structure
nornweave/
├── src/nornweave/ # Main Python package
│ ├── adapters/ # Email provider adapters (Mailgun, SES, SendGrid, Resend, SMTP/IMAP, demo)
│ ├── core/ # Core utilities (config, exceptions, interfaces)
│ ├── models/ # Pydantic/SQLAlchemy models (Event, Inbox, Message, Thread)
│ ├── huginn/ # MCP Resources (read operations for AI agents)
│ ├── muninn/ # MCP Tools (write operations for AI agents)
│ ├── skuld/ # Outbound layer (rate limiting, scheduling, sending, webhooks)
│ ├── urdr/ # Storage layer (database adapters, migrations)
│ │ ├── adapters/ # PostgreSQL and SQLite adapters
│ │ └── migrations/ # Alembic migration scripts
│ ├── verdandi/ # Ingestion (webhook + IMAP, parsing, threading, attachments, LLM summarization)
│ └── yggdrasil/ # FastAPI gateway
│ ├── middleware/ # Auth and logging middleware
│ └── routes/ # API routes (v1/, webhooks/, v1/demo when in demo mode)
├── clients/ # SDK clients for NornWeave API
│ └── python/ # Python client library (nornweave-client)
├── packages/ # External platform integrations
│ └── n8n-nodes-nornweave/ # n8n community node for NornWeave
├── tests/ # Test suite (fixtures/, integration/, unit/, e2e/)
├── web/ # Hugo documentation website
│ └── content/docs/ # Documentation content
├── scripts/ # Utility scripts (DB init, migrations, dev setup)
├── skills/ # Distributable AI assistant skills for NornWeave
├── openspec/ # OpenSpec artifacts (specs, changes, context for implementations)
│ ├── specs/ # Feature specifications and design documents
│ └── changes/archive/ # Completed and archived changes
└── .github/ # CI/CD workflows
Architecture Overview
NornWeave uses a thematic architecture inspired by Norse mythology:
| Module | Name | Purpose |
|---|---|---|
urdr |
The Well | Storage layer - PostgreSQL/SQLite adapters, Alembic migrations |
verdandi |
The Loom | Ingestion - webhook + IMAP, HTML→Markdown, threading, LLM thread summarization |
skuld |
The Prophecy | Outbound - rate limiting, scheduling, email sending |
yggdrasil |
World Tree | FastAPI gateway - routes, middleware, API endpoints |
huginn |
Thought Raven | MCP Resources - read operations for AI agents |
muninn |
Memory Raven | MCP Tools - write operations for AI agents |
Technology Stack
- Python: 3.14+ with full type hints
- Web Framework: FastAPI with async/await
- Validation: Pydantic v2 with
pydantic-settings - Database: SQLAlchemy 2.0 (async) with PostgreSQL (asyncpg) or SQLite (aiosqlite)
- Migrations: Alembic
- AI Integration: MCP SDK for Claude/Cursor integration
- HTTP Client: httpx (async)
- Package Manager: uv
- Linting/Formatting: Ruff
- Type Checking: MyPy (strict mode)
- Testing: pytest with pytest-asyncio
- Documentation: Hugo static site
Development Guidelines
General Principles
- Type safety: All functions must have complete type hints
- Async-first: Use async/await for all I/O operations
- Documentation: Docstrings for all public functions and classes
- Testing: Unit tests for business logic, integration tests for API endpoints
- Security: Never hardcode credentials; use environment variables
Python Code Style
- Follow PEP 8 (enforced by Ruff)
- Line length: 100 characters
- Use double quotes for strings
- Use
pathlib.Pathoveros.path - Use comprehensions where they improve readability
- Prefer
httpxfor HTTP requests (async support)
FastAPI Best Practices
- Use dependency injection via
Depends() - Define request/response models with Pydantic
- Use
HTTPExceptionfor error responses with appropriate status codes - Group routes in routers, version API endpoints (e.g.,
/v1/) - Add OpenAPI documentation to endpoints
Database Guidelines
- Use SQLAlchemy async sessions
- Define models in
src/nornweave/models/ - Create Alembic migrations for all schema changes in
src/nornweave/urdr/migrations/ - Use repository pattern for data access in
urdr/adapters/ - Support both PostgreSQL (production) and SQLite (development/testing)
MCP Integration
- Resources (read-only data) go in
huginn/ - Tools (actions) go in
muninn/ - Follow MCP SDK patterns for tool definitions
- Include clear descriptions for AI agent consumption
Testing
- Place unit tests in
tests/unit/mirroring source structure - Place integration tests in
tests/integration/ - Use
pytest.mark.asynciofor async tests - Use fixtures from
tests/conftest.py - Test files in
tests/fixtures/(never commit real user data)
Documentation Website (web/)
- Use Hugo for static site generation
- Content in Markdown at
web/content/docs/ - Hosted on GitHub Pages
- Keep API documentation in sync with code changes
Keeping documentation in sync
When adding, changing, or removing features (e.g. providers, capabilities, architecture), update these so they stay accurate:
- README.md: Sections "Features", "Architecture", "Supported Providers", "Repository Structure", and "MCP Integration" (tools table) as relevant.
- web/content/docs/: Guides, API docs, and concept pages that describe the feature.
- .cursor/rules/main.mdc: "Repository Structure" and "Architecture Overview" (and this list if doc locations change). Prefer a single commit that includes both the code change and the doc/rule updates.
File Organization
- Module names: snake_case
- Class names: PascalCase
- Constants: UPPER_SNAKE_CASE
- Pydantic models:
*Schemafor API,*Modelfor DB - Each module should have an
__init__.pyexposing public API
Git Workflow
- Use conventional commits:
feat:,fix:,docs:,refactor:,test:,chore: - Keep commits focused and atomic
- Reference issue numbers when applicable (e.g.,
feat: add mailgun webhook (#42)) - Run
make lintandmake testbefore committing
OpenSpec Workflow
This repository uses OpenSpec for structured feature development and change management. OpenSpec artifacts provide detailed specifications, design decisions, and implementation context.
Directory Structure
openspec/specs/- Active feature specifications and design documentsopenspec/changes/archive/- Completed changes for historical reference
When to Use OpenSpec
- Before implementing: Check
openspec/specs/for existing specifications related to your task - For context: Specs contain rationale, API designs, data models, and implementation details
- As reference: Archived changes show how similar features were implemented
Spec Contents
Each spec typically includes:
- Problem statement and goals
- API design and data models
- Implementation approach and technical decisions
- Edge cases and error handling
- Testing strategy
Common Commands
make install-dev # Install dependencies with dev extras
make dev # Run development server
make test # Run test suite
make lint # Run Ruff linter
make format # Format code with Ruff
make migrate # Run database migrations
make typecheck # Run MyPy type checker
AI Assistant Guidelines
When working in this codebase:
- Module awareness: Understand the Norse mythology naming and purpose of each module
- Async patterns: All database and HTTP operations must be async
- Type hints: Always include complete type annotations
- Provider abstraction: Email providers are abstracted in
adapters/- maintain this pattern - MCP compatibility: When adding features, consider MCP tool/resource exposure for AI agents
- OpenSpec context: Check
openspec/specs/for detailed specifications before implementing features - specs contain design decisions, API contracts, and implementation guidance - Doc sync: When implementing or changing user-facing features, update README.md, relevant
web/content/docs/pages, and.cursor/rules/main.mdc(Repository Structure / Architecture) so they stay accurate - .env file: Use
.env.exampleas a template for.envfile and keep it up to date with the latest environment variables.