You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
memos/CLAUDE.md

11 KiB

CLAUDE.md

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

Project Overview

Memos is a lightweight, self-hosted knowledge management and note-taking platform. The architecture pairs a Go backend with a React+Vite frontend, using gRPC for internal communication and providing REST API access via gRPC-Gateway.

Development Commands

Backend (Go)

Start Development Server:

go run ./cmd/memos --mode dev --port 8081

Build Binary:

go build ./cmd/memos

Run Tests:

go test ./...                    # All tests
go test ./store/...              # Store layer tests only
go test ./server/router/api/v1/test/...  # API tests

Lint:

golangci-lint run                # Full lint check (uses .golangci.yaml)

Generate Protocol Buffers:

cd proto
buf generate                     # Generate Go/TypeScript from .proto files
buf format -w                    # Format proto files

Frontend (React + Vite)

Install Dependencies:

cd web
pnpm install

Development Server:

cd web
pnpm dev                         # Hot-reload dev server (typically :5173)

Build:

cd web
pnpm build                       # Build to web/dist/
pnpm release                     # Build and copy to server/router/frontend/dist/

Lint:

cd web
pnpm lint                        # TypeScript check + ESLint

CLI Flags and Environment Variables

The backend accepts the following configuration via flags or MEMOS_* environment variables:

  • --mode / MEMOS_MODE - Runtime mode: dev, prod, demo (default: prod)
  • --addr / MEMOS_ADDR - Bind address (default: 0.0.0.0)
  • --port / MEMOS_PORT - HTTP/gRPC port (default: 5230)
  • --unix-sock / MEMOS_UNIX_SOCK - Unix socket path (optional)
  • --data / MEMOS_DATA - Data directory for SQLite (default: ~/.memos)
  • --driver / MEMOS_DRIVER - Database driver: sqlite, mysql, postgres (default: sqlite)
  • --dsn / MEMOS_DSN - Database connection string (for MySQL/PostgreSQL)
  • --instance-url / MEMOS_INSTANCE_URL - Public instance URL for webhooks/OAuth

Architecture

High-Level Structure

cmd/memos/           # CLI entry point, starts HTTP+gRPC server
server/              # HTTP server and routing
  ├── router/api/v1/ # gRPC services + gRPC-Gateway REST handlers
  ├── router/frontend/ # Embedded SPA static file serving
  └── router/rss/    # RSS feed generation
internal/            # Shared domain logic and utilities
  ├── base/          # Base types and constants
  ├── profile/       # Configuration profile handling
  ├── util/          # Utility functions
  └── version/       # Version information
store/               # Data persistence layer (repository pattern)
  ├── db/            # Database driver implementations
  │   ├── sqlite/    # SQLite driver + migrations
  │   ├── mysql/     # MySQL driver + migrations
  │   └── postgres/  # PostgreSQL driver + migrations
  └── cache/         # In-memory caching
proto/               # Protocol Buffer definitions
  └── api/v1/        # API service contracts (.proto files)
web/                 # Frontend React application
  ├── src/
  │   ├── components/ # React components
  │   ├── pages/     # Page-level components
  │   ├── store/     # MobX state management
  │   ├── router/    # React Router configuration
  │   ├── locales/   # i18n translation files
  │   ├── hooks/     # Custom React hooks
  │   └── utils/     # Utility functions
  └── public/        # Static assets

API Architecture

Dual Protocol Serving: The server uses cmux (connection multiplexer) to serve both gRPC and HTTP on the same port:

  • HTTP/2 + application/grpc → Native gRPC server
  • HTTP/1.1 → Echo server (REST API via gRPC-Gateway, static files, RSS)

API Services (defined in proto/api/v1/*.proto):

  • WorkspaceService - Workspace settings and profiles
  • AuthService - Authentication and session management
  • UserService - User management
  • MemoService - Core memo CRUD operations
  • AttachmentService - File uploads and storage
  • InboxService - Inbox items
  • ActivityService - Activity logging
  • MarkdownService - Markdown utilities (link metadata, etc.)
  • IdentityProviderService - OAuth/SSO providers
  • ShortcutService - User shortcuts

API Access Methods:

  1. Native gRPC - Direct gRPC calls to memos.api.v1.* services
  2. REST API - HTTP REST at /api/v1/* (via gRPC-Gateway)
  3. gRPC-Web - Browser gRPC calls to /memos.api.v1.* (via grpc-web proxy)

Database Layer

Store Interface: The store.Driver interface (store/driver.go) defines all data access methods. Three implementations exist:

  • store/db/sqlite/ - SQLite driver (default, embedded database)
  • store/db/mysql/ - MySQL driver
  • store/db/postgres/ - PostgreSQL driver

Migrations: Each driver contains its own migration files in subdirectories. Schema version tracking is stored in workspace_setting (key: bb.general.version). The store/migrator.go orchestrates migrations across all drivers.

Key Models:

  • Memo - Core note/memo entity
  • User - User accounts
  • Attachment - Uploaded files and images
  • MemoRelation - Graph relationships between memos
  • Activity - Activity log entries
  • Inbox - Inbox items
  • Reaction - Emoji reactions
  • WorkspaceSetting - Workspace-level configuration
  • UserSetting - User preferences
  • IdentityProvider - OAuth/SSO provider configs

Frontend Architecture

Tech Stack:

  • Framework: React 18 with TypeScript
  • Build Tool: Vite 7
  • Routing: React Router 7
  • State Management: MobX
  • Styling: Tailwind CSS 4 + Emotion
  • UI Components: Radix UI primitives
  • i18n: react-i18next with language files in web/src/locales/

State Management: MobX stores in web/src/store/ handle global state:

  • userStore - Current user session
  • memoStore - Memo collection and filters
  • editorStore - Memo editor state
  • dialogStore - Modal dialogs
  • etc.

gRPC-Web Client: The frontend uses nice-grpc-web to call backend services. Client setup is in web/src/grpcweb.ts.

Authentication

Dual Auth Support:

  1. Session-based (Cookie): user_session cookie with format {userID}-{sessionID}
  2. Token-based (JWT): Authorization: Bearer <token> header

Flow:

  • Authentication interceptor (server/router/api/v1/acl.go) runs on all gRPC methods
  • Public endpoints bypass auth (see acl_config.go for allowlist)
  • Context values set: userIDContextKey, sessionIDContextKey, accessTokenContextKey
  • Sessions have sliding expiration (14 days from last access)

Code Style and Conventions

Go

  • Formatting: All code must be gofmt-compliant (tabs for indentation)
  • Imports: Group stdlib, external, and local imports (enforced by goimports)
  • Error Handling: Wrap errors with %w when propagating: errors.Wrap(err, "context")
  • Naming: Package names lowercase, no underscores
  • Linting: Enforced via .golangci.yaml (revive, staticcheck, gocritic, etc.)

TypeScript/React

  • Components: PascalCase filenames (e.g., MemoEditor.tsx)
  • Hooks: camelCase filenames (e.g., useMemoList.ts)
  • Formatting: Prettier enforced (see web/.prettierrc.js)
  • Import Ordering: Managed by @trivago/prettier-plugin-sort-imports
  • Styling: Tailwind utility classes preferred over custom CSS

Commit Messages

Follow Conventional Commits format:

  • feat(scope): description - New features
  • fix(scope): description - Bug fixes
  • chore(scope): description - Maintenance tasks
  • refactor(scope): description - Code restructuring
  • test(scope): description - Test additions/fixes
  • docs(scope): description - Documentation updates

Scopes: server, api, store, web, proto, etc.

Testing

Go Tests:

  • Test files: *_test.go alongside source files
  • Run specific package: go test ./store/cache/...
  • API integration tests: server/router/api/v1/test/*_test.go
  • Prefer table-driven tests for multiple test cases

Frontend: Currently relies on linting and manual testing. For UI changes, validate with local dev server.

Protocol Buffer Workflow

Prerequisites: Install buf

Modifying APIs:

  1. Edit .proto files in proto/api/v1/
  2. Run cd proto && buf generate to regenerate Go and TypeScript code
  3. Update service implementations in server/router/api/v1/
  4. Update frontend gRPC-Web clients in web/src/

Generated Code Locations:

  • Go: proto/gen/api/v1/
  • TypeScript: web/src/types/proto/api/v1/

Database Migrations

When adding database schema changes:

  1. Create migration file in driver-specific directory:

    • SQLite: store/db/sqlite/migration/
    • MySQL: store/db/mysql/migration/
    • PostgreSQL: store/db/postgres/migration/
  2. Follow naming: prod_YYYYMMDD_description.sql

  3. Update schema version constant in store/migrator.go

  4. Test migration locally with all three database drivers

Common Patterns

Adding a New API Endpoint

  1. Define service method in proto/api/v1/{service}_service.proto
  2. Run buf generate to regenerate code
  3. Implement method in server/router/api/v1/{service}_service.go
  4. Add to public allowlist in acl_config.go if unauthenticated
  5. Update frontend client in web/src/

Adding a New Data Model

  1. Define struct in store/{model}.go
  2. Add CRUD methods to store.Driver interface in store/driver.go
  3. Implement methods in each driver:
    • store/db/sqlite/{model}.go
    • store/db/mysql/{model}.go
    • store/db/postgres/{model}.go
  4. Create migration files for schema changes
  5. Add tests in store/test/{model}_test.go

Frontend Data Fetching

Use gRPC-Web client from web/src/grpcweb.ts:

import { memoServiceClient } from "@/grpcweb";

const response = await memoServiceClient.listMemos({
  filter: "creator == 'users/1'",
});

State is typically managed in MobX stores (web/src/store/).

Production Deployment

Docker (Recommended):

docker run -d \
  --name memos \
  -p 5230:5230 \
  -v ~/.memos:/var/opt/memos \
  neosmemo/memos:stable

From Source:

  1. Build frontend: cd web && pnpm install && pnpm release
  2. Build backend: go build -o memos ./cmd/memos
  3. Run: ./memos --mode prod --port 5230

Data Directory: For SQLite (default), all data is stored in the directory specified by --data flag. This includes:

  • memos_prod.db - SQLite database
  • assets/ - Uploaded files (unless using S3-compatible storage)

Key Dependencies

Backend:

  • github.com/spf13/cobra - CLI framework
  • github.com/spf13/viper - Configuration management
  • google.golang.org/grpc - gRPC server
  • github.com/grpc-ecosystem/grpc-gateway/v2 - REST gateway
  • github.com/labstack/echo/v4 - HTTP server
  • github.com/soheilhy/cmux - Connection multiplexing
  • modernc.org/sqlite - Pure Go SQLite driver
  • github.com/golang-jwt/jwt/v5 - JWT authentication

Frontend:

  • react / react-dom - UI framework
  • react-router-dom - Routing
  • mobx / mobx-react-lite - State management
  • tailwindcss - Styling
  • nice-grpc-web - gRPC-Web client
  • @radix-ui/* - Headless UI components
  • react-i18next - Internationalization