docs: rewrite agent repository guide

pull/6017/head
boojack 1 month ago
parent 2a4638b332
commit 5e71c0a737

@ -1,105 +1,125 @@
# AGENTS.md
This file provides guidance to AI coding agents when working with code in this repository.
Repository instructions for AI coding agents. Keep this file short, concrete, and tied to commands that actually work in this
repo. If a fact here conflicts with source files or CI config, trust the source file and update this guide.
Self-hosted note-taking tool. Go 1.26 backend (Echo v5, Connect RPC + gRPC-Gateway), React 18 + TypeScript 6 + Vite 7 frontend, Protocol Buffers API, SQLite/MySQL/PostgreSQL.
## Project Snapshot
Memos is a self-hosted note-taking app.
- Backend: Go 1.26.2, Echo v5, Connect RPC, gRPC-Gateway, Protocol Buffers.
- Frontend: React 19, TypeScript 6, Vite 8, Tailwind CSS v4, React Query v5.
- Storage: SQLite, MySQL, PostgreSQL.
- Generated API outputs: `proto/gen/` for Go/OpenAPI, `web/src/types/proto/` for TypeScript.
## Working Rules
- Read relevant code before editing; prefer local patterns over new abstractions.
- Keep diffs scoped. Do not do repo-wide cleanup, dependency churn, or generated-file rewrites unless the task requires it.
- Do not hand-edit generated proto outputs. Change `.proto` files, then run `buf generate`.
- Add migrations for all database drivers when schema changes, and update each driver's `LATEST.sql`.
- Add public API endpoints to `server/router/api/v1/acl_config.go`.
- Ask before adding heavy dependencies, changing auth/token behavior, or altering Docker/release workflows.
## Commands
Run from the repository root unless a command starts with `cd`.
```bash
# Backend
go run ./cmd/memos --port 8081 # Start dev server
go test ./... # Run all tests
go test -v ./store/... # Run store tests (all 3 DB drivers via TestContainers)
go test -v -race ./server/... # Run server tests with race detection
go test -v -race ./internal/... # Run internal package tests with race detection
go test -v -run TestFoo ./pkg/... # Run a single test
go run ./cmd/memos --port 8081 # Start backend dev server
go test ./... # Run all Go tests
go test -v ./store/... # Store tests, including DB drivers via TestContainers
go test -v -race ./server/... # Server tests with race detector
go test -v -race ./internal/... # Internal package tests with race detector
go test -v -run TestFoo ./pkg/... # Run matching Go tests
go mod tidy -go=1.26.2 # Match CI tidy check
golangci-lint run # Lint (v2, config: .golangci.yaml)
golangci-lint run --fix # Auto-fix lint issues (includes goimports)
# Frontend (cd web)
pnpm install # Install deps
pnpm dev # Dev server (:3001, proxies API to :8081)
pnpm lint # Type check + Biome lint
pnpm lint:fix # Auto-fix lint issues
pnpm format # Format code
pnpm build # Production build
pnpm release # Build to server/router/frontend/dist
# Protocol Buffers (cd proto)
buf generate # Regenerate Go + TypeScript + OpenAPI
buf lint # Lint proto files
buf format -w # Format proto files
```
## Architecture
```
cmd/memos/main.go # Cobra CLI + Viper config, server init
server/
├── server.go # Echo v5 HTTP server, background runners
├── auth/ # JWT access (15min) + refresh (30d) tokens, PAT
├── router/
│ ├── api/v1/ # 8 gRPC services (Connect + Gateway)
│ │ ├── acl_config.go # Public endpoints whitelist
│ │ ├── sse_hub.go # Server-Sent Events (live updates)
│ ├── frontend/ # SPA static file serving
│ ├── fileserver/ # Native HTTP file server (thumbnails, range requests)
│ └── rss/ # RSS feeds
└── runner/ # Background: memo payload processing, S3 presign refresh
store/
├── driver.go # Database driver interface
├── store.go # Store wrapper + in-memory cache (TTL 10min, max 1000)
├── migrator.go # Migration logic (LATEST.sql for fresh, incremental for upgrades)
└── db/{sqlite,mysql,postgres}/ # Driver implementations
proto/
├── api/v1/ # Service definitions
├── store/ # Internal storage messages
└── gen/ # Generated Go, TypeScript, OpenAPI
internal/ # app-private packages: scheduler, cron, email, filter (CEL),
# webhook, markdown (Goldmark), httpgetter, idp (OAuth2), storage/s3
web/src/
├── connect.ts # Connect RPC client + auth interceptor + token refresh
├── auth-state.ts # Token storage (localStorage + BroadcastChannel cross-tab)
├── contexts/ # AuthContext, InstanceContext, ViewContext, MemoFilterContext
├── hooks/ # React Query hooks (useMemoQueries, useUserQueries, etc.)
├── lib/query-client.ts # React Query v5 (staleTime: 30s, gcTime: 5min)
├── router/index.tsx # Route definitions
├── components/ # UI components (Radix UI primitives, MemoEditor, Settings, etc.)
├── themes/ # CSS themes (default, dark, paper) — OKLch color tokens
└── pages/ # Page components
golangci-lint run # Go lint, config: .golangci.yaml
golangci-lint run --fix # Auto-fix lint, including goimports
# Frontend
cd web && pnpm install # Install dependencies
cd web && pnpm dev # Dev server on :3001, proxying API to :8081
cd web && pnpm lint # Type check + Biome lint
cd web && pnpm test # Vitest unit tests
cd web && pnpm build # Production build
cd web && pnpm release # Build SPA into server/router/frontend/dist
# Protocol Buffers
cd proto && buf generate # Regenerate Go + TypeScript + OpenAPI
cd proto && buf lint # Lint proto files
cd proto && buf format -w # Format proto files
```
## Conventions
### Go
- **Errors:** `errors.Wrap(err, "context")` from `github.com/pkg/errors`. Never `fmt.Errorf` (lint-enforced via forbidigo).
- **gRPC errors:** `status.Errorf(codes.X, "message")` from service methods.
- **Imports:** stdlib, then third-party, then local (`github.com/usememos/memos`). Enforced by goimports (runs as golangci-lint formatter).
- **Comments:** All exported functions must have doc comments (godot enforced).
### Frontend
- **Imports:** Use `@/` alias for absolute imports.
- **Formatting:** Biome — 140 char lines, double quotes, always semicolons, 2-space indent.
- **State:** Server data via React Query hooks (`hooks/`). Client state via React Context (`contexts/`).
- **Styling:** Tailwind CSS v4 (`@tailwindcss/vite`), `cn()` utility (clsx + tailwind-merge), CVA for variants.
### Database & Proto
- **DB changes:** Migration files for all 3 drivers + update `LATEST.sql`.
- **Proto changes:** Run `buf generate`. Generated code: `proto/gen/` and `web/src/types/proto/`.
- **Public endpoints:** Add to `server/router/api/v1/acl_config.go`.
## CI/CD
- **backend-tests.yml:** Go 1.26.2, `go mod tidy -go=1.26.2`, golangci-lint v2.11.3, tests parallelized by group (store, server, internal, other)
- **build-canary-image.yml:** Builds frontend with `pnpm release`, then publishes canary multi-arch container images for linux/amd64 and linux/arm64
- **frontend-tests.yml:** Node 24, pnpm 11, lint + build
- **proto-linter.yml:** buf lint + format check
- **release.yml:** On version tags, builds frontend once, packages binaries for Linux/macOS/Windows, and publishes release container images/tags
- **Docker:** Multi-stage (`scripts/Dockerfile`), Alpine 3.21, non-root user, port 5230, multi-arch (amd64/arm64/arm/v7)
## Code Map
| Path | Purpose |
| --- | --- |
| `cmd/memos/main.go` | Cobra/Viper CLI setup and server startup |
| `server/server.go` | Echo HTTP server and background runner wiring |
| `server/auth/` | JWT access tokens, refresh tokens, PAT handling |
| `server/router/api/v1/` | Connect/gRPC-Gateway services, ACL config, SSE hub |
| `server/router/frontend/` | Static SPA serving |
| `server/router/fileserver/` | Native HTTP file serving, thumbnails, range requests |
| `server/runner/` | Background memo processing and S3 presign refresh |
| `store/` | Store facade, cache, migrations, driver interface |
| `store/db/{sqlite,mysql,postgres}/` | Database-specific drivers and SQL |
| `proto/api/v1/` | Public API service definitions |
| `proto/store/` | Internal storage proto messages |
| `internal/` | App-private packages: scheduler, cron, email, CEL filter, markdown, idp, S3 |
| `web/src/connect.ts` | Connect RPC clients, auth interceptor, access-token refresh |
| `web/src/auth-state.ts` | Token storage and BroadcastChannel cross-tab sync |
| `web/src/hooks/` | React Query hooks for server state |
| `web/src/contexts/` | React context for client/UI state |
| `web/src/components/` | Radix/Tailwind UI components and feature components |
| `web/src/themes/` | CSS themes using OKLch color tokens |
## Change Routing
| Change | Update | Verify |
| --- | --- | --- |
| Go service or router behavior | Service code under `server/`, tests near package | `go test -v -race ./server/...` |
| Store or migration behavior | `store/`, all three DB driver migrations, `LATEST.sql` | `go test -v ./store/...` |
| Internal package logic | Relevant `internal/` package tests | `go test -v -race ./internal/...` |
| Frontend behavior | Components/hooks/contexts under `web/src/` | `cd web && pnpm lint && pnpm test` |
| Frontend production output | Vite config or release-sensitive UI | `cd web && pnpm build` or `pnpm release` |
| Proto API | `.proto` source plus generated outputs | `cd proto && buf generate && buf lint` |
| Public unauthenticated route | `server/router/api/v1/acl_config.go` | Targeted server test or manual route check |
## Go Conventions
- Wrap errors with `errors.Wrap(err, "context")` from `github.com/pkg/errors`; do not use `fmt.Errorf`.
- Return service errors with `status.Errorf(codes.X, "message")`.
- Keep imports grouped as stdlib, third-party, then `github.com/usememos/memos`; goimports is run by golangci-lint.
- Add doc comments for exported identifiers; godot enforces exported comment punctuation.
- Avoid package-level mutable state unless the surrounding package already uses that pattern.
## Frontend Conventions
- Use `@/` for absolute imports.
- Follow Biome formatting: 2-space indent, double quotes, semicolons, 140-character line width.
- Put server data in React Query hooks under `web/src/hooks/`; keep UI-only state in contexts or component state.
- Use Tailwind CSS v4 utilities, `cn()` for class merging, and CVA for variants.
- Reuse Radix primitives and existing components before adding new UI primitives.
- Keep generated proto TypeScript under `web/src/types/proto/` out of manual edits and Biome rewrites.
## Database And Proto Rules
- Schema changes require SQLite, MySQL, and PostgreSQL migrations plus `LATEST.sql` updates.
- Fresh-install SQL and incremental migrations must stay equivalent.
- Proto field changes must preserve compatibility unless the task explicitly allows a breaking API change.
- Regenerate after proto edits and include both Go/OpenAPI and TypeScript generated outputs.
## Verification Policy
- Run the narrowest relevant checks while iterating.
- Before finishing, run the checks that match the changed surface from "Change Routing".
- For docs-only changes, `git diff --check` is sufficient unless the docs include runnable examples that should be tested.
- If a required check cannot run locally, report the reason and the exact command that remains.
## CI Reference
- Backend CI: Go 1.26.2, `go mod tidy -go=1.26.2`, golangci-lint v2.11.3, test groups `store`, `server`, `internal`, `other`.
- Frontend CI: Node 24, pnpm 11.0.1, `pnpm lint`, `pnpm test`, `pnpm build`.
- Proto CI: `buf lint` and `buf format` check.
- Docker: `scripts/Dockerfile`, Alpine 3.21 runtime, non-root user, port 5230, multi-arch amd64/arm64/arm/v7.

Loading…
Cancel
Save