docs: rewrite agent repository guide

This commit is contained in:
boojack
2026-06-05 09:17:22 +08:00
parent 2a4638b332
commit 5e71c0a737
+100 -80
View File
@@ -1,105 +1,125 @@
# AGENTS.md # 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 ## Commands
Run from the repository root unless a command starts with `cd`.
```bash ```bash
# Backend # Backend
go run ./cmd/memos --port 8081 # Start dev server go run ./cmd/memos --port 8081 # Start backend dev server
go test ./... # Run all tests go test ./... # Run all Go tests
go test -v ./store/... # Run store tests (all 3 DB drivers via TestContainers) go test -v ./store/... # Store tests, including DB drivers via TestContainers
go test -v -race ./server/... # Run server tests with race detection go test -v -race ./server/... # Server tests with race detector
go test -v -race ./internal/... # Run internal package tests with race detection go test -v -race ./internal/... # Internal package tests with race detector
go test -v -run TestFoo ./pkg/... # Run a single test go test -v -run TestFoo ./pkg/... # Run matching Go tests
go mod tidy -go=1.26.2 # Match CI tidy check go mod tidy -go=1.26.2 # Match CI tidy check
golangci-lint run # Lint (v2, config: .golangci.yaml) golangci-lint run # Go lint, config: .golangci.yaml
golangci-lint run --fix # Auto-fix lint issues (includes goimports) golangci-lint run --fix # Auto-fix lint, including goimports
# Frontend (cd web) # Frontend
pnpm install # Install deps cd web && pnpm install # Install dependencies
pnpm dev # Dev server (:3001, proxies API to :8081) cd web && pnpm dev # Dev server on :3001, proxying API to :8081
pnpm lint # Type check + Biome lint cd web && pnpm lint # Type check + Biome lint
pnpm lint:fix # Auto-fix lint issues cd web && pnpm test # Vitest unit tests
pnpm format # Format code cd web && pnpm build # Production build
pnpm build # Production build cd web && pnpm release # Build SPA into server/router/frontend/dist
pnpm release # Build to server/router/frontend/dist
# Protocol Buffers (cd proto) # Protocol Buffers
buf generate # Regenerate Go + TypeScript + OpenAPI cd proto && buf generate # Regenerate Go + TypeScript + OpenAPI
buf lint # Lint proto files cd proto && buf lint # Lint proto files
buf format -w # Format proto files cd proto && buf format -w # Format proto files
``` ```
## Architecture ## Code Map
``` | Path | Purpose |
cmd/memos/main.go # Cobra CLI + Viper config, server init | --- | --- |
| `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 |
server/ ## Change Routing
├── 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/ | Change | Update | Verify |
├── driver.go # Database driver interface | --- | --- | --- |
├── store.go # Store wrapper + in-memory cache (TTL 10min, max 1000) | Go service or router behavior | Service code under `server/`, tests near package | `go test -v -race ./server/...` |
├── migrator.go # Migration logic (LATEST.sql for fresh, incremental for upgrades) | Store or migration behavior | `store/`, all three DB driver migrations, `LATEST.sql` | `go test -v ./store/...` |
└── db/{sqlite,mysql,postgres}/ # Driver implementations | 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 |
proto/ ## Go Conventions
├── api/v1/ # Service definitions
├── store/ # Internal storage messages
└── gen/ # Generated Go, TypeScript, OpenAPI
internal/ # app-private packages: scheduler, cron, email, filter (CEL), - Wrap errors with `errors.Wrap(err, "context")` from `github.com/pkg/errors`; do not use `fmt.Errorf`.
# webhook, markdown (Goldmark), httpgetter, idp (OAuth2), storage/s3 - 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.
web/src/ ## Frontend Conventions
├── 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
```
## 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.
### Go ## Database And Proto Rules
- **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 - Schema changes require SQLite, MySQL, and PostgreSQL migrations plus `LATEST.sql` updates.
- **Imports:** Use `@/` alias for absolute imports. - Fresh-install SQL and incremental migrations must stay equivalent.
- **Formatting:** Biome — 140 char lines, double quotes, always semicolons, 2-space indent. - Proto field changes must preserve compatibility unless the task explicitly allows a breaking API change.
- **State:** Server data via React Query hooks (`hooks/`). Client state via React Context (`contexts/`). - Regenerate after proto edits and include both Go/OpenAPI and TypeScript generated outputs.
- **Styling:** Tailwind CSS v4 (`@tailwindcss/vite`), `cn()` utility (clsx + tailwind-merge), CVA for variants.
### Database & Proto ## Verification Policy
- **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 - 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.
- **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) ## CI Reference
- **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 - Backend CI: Go 1.26.2, `go mod tidy -go=1.26.2`, golangci-lint v2.11.3, test groups `store`, `server`, `internal`, `other`.
- **proto-linter.yml:** buf lint + format check - Frontend CI: Node 24, pnpm 11.0.1, `pnpm lint`, `pnpm test`, `pnpm build`.
- **release.yml:** On version tags, builds frontend once, packages binaries for Linux/macOS/Windows, and publishes release container images/tags - Proto CI: `buf lint` and `buf format` check.
- **Docker:** Multi-stage (`scripts/Dockerfile`), Alpine 3.21, non-root user, port 5230, multi-arch (amd64/arm64/arm/v7) - Docker: `scripts/Dockerfile`, Alpine 3.21 runtime, non-root user, port 5230, multi-arch amd64/arm64/arm/v7.