diff --git a/.gitignore b/.gitignore
index 8dbea86..ee0fbf7 100644
--- a/.gitignore
+++ b/.gitignore
@@ -72,3 +72,7 @@ check_*.py
# Environment variables
.env
.env.*
+
+# Claude Code
+CLAUDE.md
+AGENTS.md
diff --git a/AGENTS.md b/AGENTS.md
deleted file mode 100644
index d2e4220..0000000
--- a/AGENTS.md
+++ /dev/null
@@ -1,86 +0,0 @@
-# AGENTS.md
-
-## Project overview
-- Full-stack todo app: **Vue 3 + Element Plus** (WebUI/) + **FastAPI + SQLAlchemy** (api/)
-- **Python 3.10+, Node 18+**; SQLite database
-- Single `master` branch (4 commits total), no CI/CD
-
-## Quick commands
-
-```powershell
-# Install Python deps (required before first run)
-pip install -r requirements.txt
-
-# Full-stack one-shot (builds frontend, then starts backend on :23994)
-python main.py
-
-# Frontend dev only (hot-reload on :5173, proxies /api → :23994)
-cd WebUI; npm run dev
-
-# Backend only
-cd api; uvicorn app.main:app --host 0.0.0.0 --port 23994
-
-# Type-check frontend (noEmit; uses project references tsconfig)
-cd WebUI; npm run typecheck
-```
-
-**Build order matters:** `python main.py` automatically compiles WebUI (`npm install` + `npm run build`), copies `WebUI/dist/` → `api/webui/`, then starts uvicorn. It checks timestamps to skip rebuilds when frontend is unchanged.
-
-**Import path:** `main.py` injects `api/` into `sys.path` (no `os.chdir`). Backend imports resolve relative to `api/` — e.g. `from app.config import ...`, not `from api.app.config import ...`.
-
-**Port conflict:** `main.py` will auto-kill any process already listening on port 23994 before starting. If you have another instance running, it will be terminated without warning.
-
-## Architecture
-
-### Backend (`api/app/`)
-- **Config is hardcoded** in `api/app/config.py` — no `.env`, no `os.getenv()`. Port `23994`, CORS origins `["http://localhost:5173", "http://localhost:23994"]`. Note: `pydantic-settings` is in `requirements.txt` but unused.
-- **SQLite path** is computed relative to `api/` via `__file__` — safe regardless of cwd. `connect_args={"check_same_thread": False}` for FastAPI async compatibility.
-- **`database.py:init_db()`** auto-creates tables on startup (`create_all`) and auto-adds missing columns via `ALTER TABLE ADD COLUMN` (no Alembic). Columns that are non-nullable with no default are skipped.
-- **UserSettings is a singleton**: always id=1, auto-created on first `GET`. `set_default_password()` auto-initializes password to `"elysia"` on first access if `password_hash` is empty.
-- **Habit checkins for the same day** accumulate count (not new rows), enforced by a `(habit_id, checkin_date)` unique constraint. Cancelling reduces count; deleting when count ≤ 0 removes the row.
-- **Anniversaries** have computed fields (`next_date`, `days_until`, `year_count`) calculated at request time, not stored in DB. The calculation functions live in the router layer (not models), because they depend on `date.today()`.
-- **`task_tags` M2M table** is defined in `models/tag.py` (not `models/task.py`). Tags only support create/delete (no update).
-- **Update schemas** use `clearable_fields` + `exclude_unset=True` to distinguish "field not sent" from "field sent as null". For non-clearable fields, `None` means "don't change"; for clearable fields, `None` means "clear it". See `schemas/task.py:TaskUpdate`, `schemas/habit.py:HabitUpdate`, `schemas/anniversary.py:AnniversaryUpdate`.
-- **JWT authentication** — `utils/auth.py` handles JWT (HS256, key: `"elysia-todo-secret-key-change-in-production"`, 24h expiry). Middleware in `main.py` validates tokens for all `/api/*` routes except `/api/auth/*` and `/health`. Default password: `elysia`. Login via `POST /api/auth/login`. Token key in localStorage: `elysia_auth_token`. **Middleware only validates the token; it does NOT inject user info into `request.state`.** Routes needing user data must call `get_current_user(request)` manually.
-- **Different cascade delete strategies:**
- - `Category`: refuses deletion if tasks are linked (400)
- - `HabitGroup`: sets linked habits' `group_id` to NULL
- - `AnniversaryCategory`: sets linked anniversaries' `category_id` to NULL
-
-### Router registration quirks
-- **`/health` MUST be registered before `/{full_path:path}`** in `main.py:114` — otherwise SPA fallback intercepts health checks and returns `index.html`.
-- **habits router** (`routers/habits.py`) is an empty-shell router that combines 3 sub-routers via `include_router`: habit-groups (`/api/habit-groups`), habits (`/api/habits`), and checkins (`/api/habits/{habit_id}/checkins`).
-- **anniversaries router** uses `prefix="/api"` (not `/api/anniversaries`). Its internal paths are `/anniversaries`, `/anniversary-categories`, etc.
-
-### Frontend (`WebUI/`)
-- Vue Router uses `createWebHistory()` (HTML5 history mode) — **requires the backend SPA fallback** (`/{full_path:path}` → `index.html`).
-- Vite dev proxy forwards `/api` → `http://localhost:23994`.
-- `@` alias maps to `src/`.
-- 8 Pinia stores: `auth`, `task`, `category`, `tag`, `habit`, `anniversary`, `userSettings`, `ui`. The `ui` store manages dialog visibility, editing state, sidebar collapse, and global loading (no API calls).
-- Element Plus icons registered globally in `main.ts` — use ``, `` etc. in templates without imports.
-- Element Plus uses Chinese locale (`zh-cn`).
-- **Vite 7.x + TypeScript 5.9** with `erasableSyntaxOnly: true` and project references.
-- **Frontend task filtering is entirely client-side.** `fetchTasks()` loads all tasks once; filtering, sorting, and pinyin search run in computed getters. No server-side filtering for tasks.
-- **Pinyin search** via `pinyin-pro` (`utils/pinyin.ts`) — supports Chinese character search by pinyin initials or full pinyin.
-- **Token key `elysia_auth_token` is hardcoded in 3 separate files** (`router/index.ts`, `api/request.ts`, `stores/useAuthStore.ts`). If you rename it, update all 3.
-- **401 response triggers a hard page redirect** (`window.location.href = '/login'`) in the axios interceptor, which reloads the SPA entirely. This differs from the router guard's in-app redirect (`return { path: '/login' }`).
-- `sass` is a runtime `dependency` (not `devDependency`) in `package.json` — intentional.
-
-### Docker
-- `Dockerfile` copies pre-built `api/webui/` — you must build frontend before `docker build`.
-- Docker CMD is an inline `python -c` one-liner that injects `api/` into `sys.path` and starts uvicorn. No separate entrypoint script.
-- `docker-compose.yml` mounts `api/data/` and `api/logs/` for persistence; `api/webui/` is read-only.
-
-## Testing quirks
-- No test framework or test files currently in the repo.
-- No test coverage for tasks, habits, anniversaries, or tags.
-
-## What's missing (agents should not assume)
-- No linter, formatter, pre-commit hooks, or CI/CD
-- No `.env` or environment variable loading
-- No database migrations framework (Alembic)
-
-## Additional notes
-- Swagger UI at `/docs` when backend is running.
-- `python-multipart` in `requirements.txt` is required for FastAPI to parse form data (not optional).
-- `pydantic-settings` is installed but unused — config is hardcoded.