Skip to main content
This guide covers setting up a development environment for Basic Memory and running tests.

Prerequisites

Python 3.12+

Basic Memory requires Python 3.12 or later

uv (recommended)

Fast Python package manager and project tool

just (optional)

Modern command runner for development tasks

Docker (optional)

Required for PostgreSQL integration tests

Installation

1

Clone the repository

git clone https://github.com/basicmachines-co/basic-memory.git
cd basic-memory
2

Install dependencies

3

Activate virtual environment

source .venv/bin/activate
4

Verify installation

# Run tests
just test-unit-sqlite

# Or manually
pytest tests/ -v

Development Commands

Basic Memory uses just as a command runner. View all available commands:
just --list

Code Quality

# Lint and auto-fix
just lint

# Format code
just format

# Type checking (pyright)
just typecheck

# Type checking (ty - supplemental)
just typecheck-ty

# Run all quality checks
just check

Testing

# Run all tests (SQLite + Postgres)
just test

# SQLite only (fast)
just test-sqlite

# Unit tests only
just test-unit-sqlite

# Integration tests only
just test-int-sqlite

Fast Development Loop

# Fix, format, typecheck, test changed files, smoke test
just fast-check
This runs:
  1. just fix - Auto-fix linting issues
  2. just format - Format code with ruff
  3. just typecheck - Type check with pyright
  4. just testmon - Test only changed files
  5. just test-smoke - Fast MCP integration test

Database Migrations

Create a new database migration:
just migration "Add new feature"
This creates a new Alembic migration file in src/basic_memory/alembic/versions/. Migrations run automatically on startup:
bm status  # Triggers migration check

Testing Architecture

Test Structure

Basic Memory has two test directories:
Unit tests - Fast, isolated, mocked
tests/
├── test_config.py
├── test_entity_repository.py
├── test_markdown_parser.py
└── ...
Characteristics:
  • Test individual functions/classes
  • Use mocks for dependencies
  • Fast execution (< 1 second per test)
  • Run with: just test-unit-sqlite

Dual Backend Testing

All tests run against both SQLite and PostgreSQL:
# SQLite tests (fast, no Docker)
just test-sqlite

# PostgreSQL tests (uses testcontainers)
just test-postgres

# Run both
just test
PostgreSQL tests use testcontainers to automatically spin up a PostgreSQL container. Docker must be running.

Test Markers

Tests use pytest markers for selective execution:
@pytest.mark.benchmark  # Performance benchmarks
@pytest.mark.slow       # Slow-running tests (> 5 seconds)
@pytest.mark.postgres   # PostgreSQL-specific tests
@pytest.mark.windows    # Windows-specific tests
@pytest.mark.smoke      # Fast MCP smoke tests
@pytest.mark.semantic   # Semantic search tests
Run specific markers:
# Exclude benchmarks
pytest -m "not benchmark"

# Run only smoke tests
pytest -m smoke

# Run semantic search tests
pytest -m semantic

Code Style Guidelines

Python 3.12+ required for:
  • Type parameter syntax (def func[T](...))
  • Type aliases (type MyType = str | int)
  • Line length: 100 characters max
  • Tool: ruff (replaces black, isort, flake8)
  • Import order: standard lib → third-party → local
  • Functions/variables: snake_case
  • Classes: PascalCase
  • Constants: UPPER_SNAKE_CASE
  • Private members: _leading_underscore
  • Required for all public functions
  • Use modern syntax: list[str] not List[str]
  • Use | None not Optional[T]
  • Document complex types with type aliases
  • Prefer async/await throughout
  • Use SQLAlchemy 2.0 async ORM
  • Use aiofiles for file I/O
  • Use asyncpg for PostgreSQL

Debugging

Logging

Basic Memory uses Loguru for logging:
# Set log level
export BASIC_MEMORY_LOG_LEVEL=DEBUG

# View logs
tail -f ~/.basic-memory/basic-memory.log

MCP Inspector

Test MCP tools interactively:
just run-inspector
This starts the MCP Inspector UI for testing tools.

Doctor Command

Check file ↔ database consistency:
# Run in temp environment (safe)
just doctor

# Run on actual project
bm doctor

Continuous Integration

CI runs on GitHub Actions:
# .github/workflows/test.yml
jobs:
  test-sqlite:
    runs-on: ubuntu-latest
    steps:
      - run: just test-sqlite
  
  test-postgres:
    runs-on: ubuntu-latest
    steps:
      - run: just test-postgres
Requirements for CI to pass:
  • ✅ All tests pass (SQLite and Postgres)
  • ✅ Linting passes (just lint)
  • ✅ Type checking passes (just typecheck)
  • ✅ Code coverage ≥ target threshold

Contributing Workflow

1

Fork and clone

Fork the repository on GitHub and clone your fork
2

Create a branch

git checkout -b feature/your-feature-name
3

Make changes

Implement your feature with tests and documentation
4

Run quality checks

just check
5

Commit with sign-off

git commit -s -m "Add new feature"
The -s flag signs off on the Developer Certificate of Origin
6

Push and create PR

git push origin feature/your-feature-name
Then create a pull request on GitHub

Release Process

Basic Memory uses automatic versioning with uv-dynamic-versioning:
Published automatically on every commit to main:
# Version format: 0.12.4.dev26+468a22f
pip install basic-memory --pre --force-reinstall

Resources

Architecture

Learn about the system architecture

Contributing Guide

Full contributing guidelines

GitHub Repository

View source code and issues

Discord Community

Get help and discuss development

Build docs developers (and LLMs) love