·

Tiếng Việt: Providing Codebase Context

Providing Codebase Context

Một AI coding agent chỉ giỏi bằng thứ nó nhìn thấy: dạy nó "đọc" đúng phần codebase của bạn, và năng suất coding sẽ tăng gấp nhiều lần.

AI Coding Tool Index Repository Của Bạn Như Thế Nào

Trước khi bàn chuyện viết CLAUDE.md hay gõ @file, kỹ sư cần hiểu cơ chế bên dưới: làm sao Cursor, Claude Code, Windsurf hay GitHub Copilot Workspace biết được nên "nhìn" vào đâu trong một repo có thể lên tới hàng trăm nghìn dòng code, vượt xa context window (cửa sổ ngữ cảnh) của bất kỳ LLM nào hiện nay.

Về cơ bản, các công cụ này dùng kết hợp ba kỹ thuật:

1. File tree / directory listing. Đây là lớp rẻ nhất và luôn có sẵn. Khi agent khởi động trong một thư mục, nó sẽ chạy các lệnh tương đương ls -R, find, hoặc đọc .git/index để dựng cây thư mục. Cây này thường được nén lại (chỉ liệt kê tên file, bỏ nội dung) và nhét vào system prompt hoặc context ban đầu. Claude Code, ví dụ, khi bắt đầu một phiên làm việc sẽ tự động liệt kê cấu trúc thư mục gốc để có "bản đồ" sơ bộ trước khi đọc bất kỳ file nào.

2. Symbol index (chỉ mục ký hiệu). Nhiều công cụ (đặc biệt là các IDE-based như Cursor, VS Code extension) build một index kiểu ctags/LSP (Language Server Protocol) — ánh xạ tên hàm, class, biến, import tới vị trí file:line. Khi bạn hỏi "sửa hàm calculateInvoiceTotal", công cụ tra symbol index thay vì đọc toàn bộ repo, giúp tìm chính xác định nghĩa và mọi nơi gọi đến (call site) mà không tốn token brute-force.

3. Embeddings-based semantic search (tìm kiếm ngữ nghĩa dựa trên embedding). Đây là lớp "thông minh" nhất: công cụ chia codebase thành các chunk (theo file hoặc theo hàm/class), sinh vector embedding cho từng chunk, lưu vào vector database cục bộ hoặc trên cloud. Khi bạn gõ prompt, prompt cũng được encode thành embedding, rồi hệ thống tìm các chunk có similarity (độ tương đồng) cao nhất — đây chính là RAG (Retrieval-Augmented Generation) áp dụng cho code. Cursor's "Codebase Indexing", Sourcegraph Cody, và các plugin JetBrains AI đều dùng cơ chế này để trả lời câu hỏi kiểu "chỗ nào xử lý logic retry cho payment gateway?" mà không cần bạn chỉ đích danh file.

Điểm mấu chốt engineer cần nắm: các cơ chế tự động này là xác suất, không phải chắc chắn. Semantic search có thể bỏ sót file quan trọng nếu tên biến/comment không "gần nghĩa" với câu hỏi của bạn, hoặc nếu file đó nằm ngoài phạm vi được index (ví dụ bị exclude bởi .cursorignore, hoặc nằm trong submodule chưa được quét). Symbol index cũng có thể lỗi thời nếu bạn vừa refactor mà chưa re-index. Vì vậy, phần lớn bug "AI sửa sai chỗ" hoặc "AI không biết file đó tồn tại" đến từ việc quá tin tưởng vào auto-context mà không kiểm tra, hoặc không bổ sung context thủ công khi cần.

Một điểm khác biệt quan trọng giữa các công cụ: Claude Code (chạy trong terminal, có full filesystem access) có xu hướng dùng agentic exploration — tức là nó chủ động chạy grep, find, Read nhiều lần trong một task, giống hệt một kỹ sư thật sự đọc code trước khi sửa — thay vì chỉ dựa vào một index tĩnh dựng sẵn. Điều này chính xác hơn nhưng tốn nhiều lượt gọi tool (tool call) hơn. Trong khi đó, các plugin IDE thường ưu tiên index tĩnh để phản hồi nhanh trong lúc gõ code (autocomplete, inline chat).

Mẹo: Nếu nghi ngờ AI "không thấy" đúng file, đừng đoán — hỏi thẳng: "List all files you read or searched before answering." Câu trả lời sẽ lộ ra ngay lỗ hổng trong context của nó.

Manual File Inclusion: Cú Pháp @file và #file

Dù index tự động ngày càng tốt, manual inclusion (chỉ định file thủ công) vẫn là công cụ đáng tin cậy nhất để đảm bảo AI đọc đúng file bạn muốn, đúng lúc bạn cần — không phụ thuộc vào may rủi của semantic search.

Trong Cursor:@ trong ô chat sẽ mở autocomplete cho phép bạn chọn:
- @filename.ts — nhúng toàn bộ nội dung file vào context.
- @Folder — nhúng cấu trúc và (tuỳ chọn) nội dung cả thư mục.
- @Codebase — kích hoạt semantic search trên toàn repo cho câu hỏi hiện tại.
- @Docs — tham chiếu tài liệu framework đã được index (React, Next.js...).
- @Git — tham chiếu diff, commit, hoặc PR cụ thể.

Ví dụ prompt thực tế trong Cursor:

Refactor @src/services/paymentService.ts to extract the retry logic
into a separate function. Follow the same error-handling pattern used
in @src/services/emailService.ts.

Ở đây, việc chỉ định rõ hai file giúp AI không cần đoán "pattern xử lý lỗi" là gì — nó đọc trực tiếp file mẫu, giảm hallucination (bịa đặt) đáng kể so với để AI tự "nhớ" convention chung chung.

Trong Claude Code: không có cú pháp @ bắt buộc, nhưng có ba cách tương đương:
- Nhắc đường dẫn tương đối trực tiếp trong prompt (Claude Code sẽ tự gọi tool Read cho file đó): "Xem file src/services/paymentService.ts và sửa lại hàm retryPayment."
- Kéo-thả (drag-and-drop) file vào terminal (nếu terminal hỗ trợ) để chèn đường dẫn tuyệt đối.
- Dùng lệnh /add-dir hoặc mount thêm working directory khi cần AI thấy code ở ngoài repo hiện tại (ví dụ một shared library nằm ở path khác).

Ví dụ prompt cho Claude Code:

Read src/services/paymentService.ts and src/services/emailService.ts.
Refactor the retry logic in paymentService.ts into a standalone
function, following the same try/catch + exponential backoff pattern
used in emailService.ts. Do not change the public function signature.

Trong GitHub Copilot Chat: dùng cú pháp #file:đường/dẫn (hoặc gõ # để mở autocomplete chọn file/symbol) để nhúng chính xác một file vào ngữ cảnh của câu hỏi hiện tại, tương tự @file của Cursor. Copilot Chat còn hỗ trợ thêm #selection (chèn đoạn code đang bôi đen trong editor) và #codebase (kích hoạt semantic search toàn repo, tương đương @Codebase của Cursor). Ví dụ:

Refactor #file:src/services/paymentService.ts to extract the retry
logic into a separate function. Follow the same error-handling
pattern used in #file:src/services/emailService.ts.

Về bản chất, @file (Cursor), nhắc đường dẫn trực tiếp (Claude Code), và #file (Copilot Chat) đều giải quyết cùng một vấn đề — chỉ định chính xác file cần đọc — chỉ khác cú pháp bề mặt tùy công cụ. Điều quan trọng không phải là nhớ đúng ký tự @ hay #, mà là thói quen: luôn chỉ định rõ file khi bạn đã biết nó liên quan, thay vì phó mặc cho auto-context đoán.

Khi nào dùng manual, khi nào để auto?

Tình huống Nên dùng
Bạn biết chính xác 1-3 file liên quan Manual inclusion — nhanh, chính xác, tiết kiệm token
Câu hỏi khám phá kiểu "logic X nằm ở đâu trong repo?" Auto (semantic search / agentic grep)
Task sửa bug có stack trace rõ ràng Manual — dán file + stack trace
Task lớn, đa file, chưa rõ phạm vi ảnh hưởng Kết hợp: để AI tự search trước, rồi bạn xác nhận/bổ sung file còn thiếu
File nhạy cảm (config bí mật, migration DB) Luôn manual, kiểm soát chặt để tránh AI tự ý sửa nhầm

Nguyên tắc thực dụng: manual inclusion giảm token lãng phí và tăng độ chính xác, nhưng đòi hỏi bạn đã biết codebase. Với kỹ sư mới join dự án hoặc module lạ, hãy để AI tự khám phá trước (auto), sau đó chuyển sang manual một khi đã xác định đúng phạm vi — đây chính là workflow hai bước được khuyến nghị trong hầu hết codebase lớn.

Mẹo: Khi task liên quan tới nhiều file, đừng liệt kê tất cả cùng lúc trong một prompt dài dòng — hãy để AI đọc file "gốc" (entry point) trước, nó sẽ tự follow import và đọc thêm file phụ thuộc khi cần, tiết kiệm context window hơn nhiều so với nhồi sẵn toàn bộ.

Viết CLAUDE.md Chất Lượng Cao

CLAUDE.md (hoặc tương đương .cursorrules, .windsurfrules) là file context tĩnh quan trọng nhất trong một dự án dùng AI coding agent. Nó được tự động nạp vào đầu mỗi phiên làm việc, đóng vai trò như "onboarding doc" cho AI — tương tự cách bạn brief một kỹ sư mới trong ngày đầu tiên. Khác biệt là: AI đọc lại toàn bộ file này mỗi lần bắt đầu task, nên chất lượng của nó ảnh hưởng trực tiếp và liên tục tới mọi output.

Sai lầm phổ biến nhất: coi CLAUDE.md như README marketing (giới thiệu dự án chung chung) thay vì tài liệu vận hành nội bộ. README nói cho người dùng biết dự án làm gì; CLAUDE.md phải nói cho AI biết cách sửa code trong dự án này mà không phá vỡ quy ước, kiến trúc, hay side-effect ẩn.

Nội dung cần có

Một CLAUDE.md tốt, theo kinh nghiệm áp dụng cho các dự án production thực tế, cần bao phủ:

  1. Architecture Overview (tổng quan kiến trúc) — mô tả ngắn gọn hệ thống gồm những thành phần gì (frontend, backend, worker, database, third-party service), giao tiếp với nhau ra sao (REST, gRPC, message queue), và triết lý thiết kế chính (monolith hay microservices, event-driven hay request-response...). Không cần dài, nhưng phải đủ để AI hiểu "bức tranh lớn" trước khi đọc code chi tiết.

  2. Repository Structure (cấu trúc thư mục) — liệt kê các thư mục cấp cao và ý nghĩa của chúng. Đừng liệt kê máy móc mọi file — tập trung vào những thư mục AI dễ hiểu nhầm mục đích (ví dụ shared/ chứa gì, legacy/ có còn dùng không).

  3. Tech Stack (công nghệ sử dụng) — ngôn ngữ, framework, phiên bản quan trọng (đặc biệt nếu có breaking changes giữa các version), ORM, thư viện test, package manager. Giúp AI không đề xuất API đã deprecated hoặc syntax sai version.

  4. Coding Conventions (quy ước code) — style guide, quy tắc đặt tên, cách xử lý lỗi chuẩn của team, pattern bắt buộc (ví dụ luôn dùng dependency injection, luôn viết test trước khi merge), và những thứ cấm làm (ví dụ không dùng any trong TypeScript, không commit trực tiếp lên main).

  5. Key Files (file quan trọng) — chỉ đích danh các file "trung tâm" mà hầu hết task sẽ động tới hoặc cần tham chiếu: entry point, config chính, file định nghĩa route/API, schema database.

  6. Gotchas (những cái bẫy) — đây là phần giá trị nhất và hay bị bỏ quên: những hành vi phi trực giác, technical debt đã biết, workaround tạm thời, hoặc bug đã từng xảy ra do AI (hay người) hiểu nhầm code. Ví dụ: "Hàm formatDate KHÔNG xử lý timezone, luôn giả định UTC — đừng sửa trừ khi đã bàn với team," hoặc "Bảng orders có cột status legacy không còn dùng, dùng order_state thay thế."

Nguyên tắc vàng: viết CLAUDE.md như thể bạn đang review lại PR của một thực tập sinh giỏi nhưng chưa biết gì về dự án — bạn sẽ nói gì để họ không lặp lại sai lầm kinh điển của người mới?

CLAUDE.md Template

Dưới đây là một template thực tế, có thể copy và điều chỉnh cho dự án của bạn:


## Architecture Overview

[Project Name] is a [monolith / microservices / modular monolith]
system consisting of:
- `api/` — REST API server (Node.js + Express), handles auth,
  business logic, and DB access.
- `worker/` — background job processor (BullMQ), consumes queue
  jobs for email, report generation, data sync.
- `web/` — customer-facing frontend (Next.js, App Router).
- `admin/` — internal admin dashboard (React + Vite).

Communication: `web`/`admin` call `api` over REST (OpenAPI spec in
`api/openapi.yaml`). `api` pushes jobs to Redis queue consumed by
`worker`. No direct DB access from `worker` to `web`.

## Repository Structure

- `api/src/routes/` — route handlers, one file per resource.
- `api/src/services/` — business logic, framework-agnostic.
- `api/src/db/` — Prisma schema + migrations.
- `shared/` — types and utils shared between `api` and `web`
  (published as internal npm package `@project/shared`).
- `legacy/` — PHP billing module, still in production, DO NOT
  extend; new billing features go in `api/src/services/billing/`.

## Tech Stack

- Node.js 20, TypeScript 5.4 (strict mode)
- Express 4, Prisma ORM, PostgreSQL 15
- Next.js 14 (App Router, Server Components by default)
- Jest for unit tests, Playwright for E2E
- Package manager: pnpm (NOT npm/yarn — workspaces config depends
  on pnpm-lock.yaml)

## Coding Conventions

- Functions: camelCase. Types/interfaces: PascalCase. Files:
  kebab-case.
- No `any`; use `unknown` + type guards if the type is genuinely
  dynamic.
- All async DB calls go through the `services/` layer — route
  handlers must not call Prisma directly.
- Error handling: throw `AppError` subclasses (see
  `api/src/errors/`), never raw `Error`. Global handler in
  `api/src/middleware/errorHandler.ts` maps them to HTTP codes.
- Every new service function needs a unit test in the same folder
  under `__tests__/`.
- Commit messages: Conventional Commits (`feat:`, `fix:`, `chore:`).

## Key Files

- `api/src/app.ts` — Express app entry point, middleware order
  matters here.
- `api/src/db/schema.prisma` — source of truth for DB schema.
- `shared/src/types/index.ts` — canonical shared types, imported by
  both `api` and `web`.
- `web/app/layout.tsx` — root layout, holds auth context provider.

## Gotchas

- `formatCurrency()` in `shared/src/utils/money.ts` assumes USD
  cents as integers. Passing a float WILL cause silent rounding
  bugs. Always convert to cents before calling.
- `legacy/billing.php` writes directly to the `invoices` table
  used by the new API — any migration touching `invoices` must be
  coordinated with the PHP team, or billing breaks silently.
- Redis queue jobs are NOT idempotent yet (tracked in JIRA-1421).
  Do not add automatic retries without adding idempotency keys
  first.
- `NODE_ENV=test` disables rate limiting globally — do not rely on
  rate-limit behavior in tests.

Template này chỉ là khung sườn — hãy điều chỉnh mức chi tiết theo quy mô dự án. Với monorepo lớn, cân nhắc tách thành nhiều CLAUDE.md theo từng package/module (Claude Code hỗ trợ đọc CLAUDE.md lồng nhau theo thư mục con), tránh nhồi tất cả vào một file khổng lồ làm loãng tín hiệu quan trọng.

Mẹo: Review lại CLAUDE.md sau mỗi sprint như một phần checklist — nếu AI liên tục mắc cùng một lỗi (ví dụ quên convention nào đó), đó là dấu hiệu CLAUDE.md thiếu thông tin, hãy bổ sung ngay thay vì lặp lại lời nhắc trong từng prompt.

Kiểm Soát Những Gì AI Bỏ Qua: .cursorignore và Tương Tác Với .gitignore

Một khía cạnh hay bị xem nhẹ: AI coding tool không nhất thiết dùng cùng bộ lọc file với Git. Điều này tạo ra hai loại rủi ro ngược chiều nhau mà kỹ sư cần chủ động kiểm soát.

Rủi ro 1 — AI đọc phải thứ không nên đọc. .gitignore được thiết kế để loại file khỏi version control (build artifact, node_modules, file log), không phải để bảo vệ bí mật khỏi AI. Nhiều công cụ AI, mặc định, vẫn quét toàn bộ filesystem trong working directory — bao gồm cả file bị .gitignore loại trừ, ví dụ .env, secrets.yaml, credential JSON của cloud provider. Nếu những file này tồn tại trên máy (dù không commit), agent có full filesystem access (như Claude Code chạy local) hoàn toàn có thể đọc và vô tình đưa nội dung vào context, log, hoặc thậm chí output cho người khác xem trong một screen-share.

Rủi ro 2 — AI bỏ sót thứ cần đọc. Ngược lại, một số file cần AI thấy để hiểu hệ thống nhưng lại bị exclude vì lý do khác: generated code (ví dụ file .d.ts sinh từ GraphQL schema) có thể hữu ích để AI hiểu type shape, dù bị gitignore vì không cần versioning. Vendored dependency (thư viện third-party được copy thẳng vào repo) đôi khi cần AI đọc để debug tích hợp, dù thường bị ignore vì quá lớn.

Đây là lý do các công cụ như Cursor giới thiệu file .cursorignore (và Claude Code tôn trọng file tương tự tuỳ cấu hình) — một lớp kiểm soát độc lập với Git, chuyên dùng để nói cho AI biết "đừng đọc cái này," bất kể Git có track nó hay không.

Ví dụ .cursorignore thực tế cho một dự án Node.js + Next.js:

.env
.env.*
!.env.example
**/credentials.json
**/*serviceAccount*.json
.aws/
.ssh/

dist/
build/
.next/
out/
coverage/
*.tsbuildinfo

node_modules/
vendor/

*.sqlite
*.db
public/uploads/
**/*.mp4
**/*.zip

third_party/
legacy/vendor-stripe-sdk/

.vscode/
.idea/

Lưu ý các nguyên tắc khi thiết kế file này:

  • Luôn ignore mọi file .env* trừ .env.example — dùng pattern !.env.example để "un-ignore" file mẫu (không chứa giá trị thật) mà AI vẫn nên thấy để biết cần cấu hình biến môi trường nào.
  • Đừng ignore quá tay — nếu ignore cả shared/ hay src/types/, AI sẽ liên tục đoán sai type và tạo ra code không tương thích. Chỉ ignore thứ thực sự không mang thông tin (build output, binary, dependency).
  • File lớn nhưng cần thiết (ví dụ schema.prisma, openapi.yaml) không nên bị ignore dù dung lượng lớn, vì chúng là nguồn sự thật (source of truth) cho kiến trúc dữ liệu/API.
  • Với monorepo, đặt .cursorignore (hoặc tương đương) riêng cho từng package nếu cần mức độ kiểm soát khác nhau, tương tự cách CLAUDE.md có thể lồng nhau.

Về mặt vận hành, hãy đối chiếu định kỳ .cursorignore với .gitignore: chạy diff tinh thần giữa hai file, xác nhận rằng mọi thứ bí mật trong .gitignore cũng có mặt (hoặc match bởi pattern) trong .cursorignore, và không có gì quan trọng bị ignore "nhầm" chỉ vì nó từng bị thêm vào .gitignore với lý do khác (ví dụ build cache).

Mẹo: Thêm một dòng kiểm tra vào CI: cảnh báo nếu có file khớp pattern *secret*, *credential*, .env* (trừ .env.example) tồn tại trong repo mà không nằm trong cả .gitignore lẫn .cursorignore — tránh rủi ro rò rỉ qua cả hai kênh Git lẫn AI.

Hands-On: Thiết Lập Codebase Context Cho Một Tính Năng Mới

Phần này mô phỏng quy trình thực tế: bạn được giao xây dựng tính năng "gửi email nhắc nhở khi giỏ hàng bị bỏ quên" (abandoned cart reminder) cho một e-commerce backend Node.js + Prisma đã tồn tại. Đây là các bước cụ thể để thiết lập context trước khi để AI viết code, áp dụng được cho cả Claude Code lẫn Cursor.

Bước 1 — Kiểm tra và cập nhật CLAUDE.md trước khi bắt đầu.

Mở CLAUDE.md hiện có, tự hỏi: "Nếu một kỹ sư mới đọc file này, họ có đủ thông tin để biết cart, order, email service nằm ở đâu và hoạt động ra sao không?" Nếu CLAUDE.md chưa nhắc tới cart/order module, bổ sung nhanh một đoạn vào phần Key Files:

## Key Files (update)

- `api/src/services/cartService.ts` — cart CRUD, `getAbandonedCarts()`
  already exists but is unused (added for a future job).
- `api/src/services/emailService.ts` — wraps SendGrid, use
  `sendTemplateEmail(templateId, to, data)` for all outbound email.
- `worker/src/jobs/` — cron-style jobs registered in
  `worker/src/index.ts`; follow the pattern in `syncInventory.job.ts`.

Việc này tốn 2 phút nhưng giúp mọi prompt sau đó, kể cả của đồng nghiệp khác, đều có context này miễn phí.

Bước 2 — Để AI tự khám phá phạm vi ảnh hưởng (auto-context).

Trước khi giao task cụ thể, dùng một prompt khám phá để xác nhận AI hiểu đúng bức tranh và tránh việc nó code lại thứ đã tồn tại:

I need to add an "abandoned cart reminder" feature: send an email
24h after a cart has items but no completed order. Before writing
any code, explore the codebase and tell me:
1. Is there existing logic related to cart abandonment or scheduled
   email jobs?
2. Which files would need to change?
3. Any existing pattern I should follow for background jobs?
Do not write code yet — just report findings.

Bước "đừng viết code vội" rất quan trọng — nó buộc AI (và bạn) xác nhận hiểu đúng scope trước khi tốn effort implement sai hướng. Đây cũng là lúc bạn phát hiện AI có thấy đúng getAbandonedCarts() đã tồn tại sẵn hay không — nếu nó bỏ sót, đó là tín hiệu cần bổ sung manual inclusion ở bước sau.

Bước 3 — Manual inclusion cho các file "khuôn mẫu" (pattern reference).

Dựa trên kết quả khám phá, chỉ định rõ file cần theo làm mẫu, tránh AI tự sáng tạo convention mới:

Read worker/src/jobs/syncInventory.job.ts, api/src/services/cartService.ts,
and api/src/services/emailService.ts.

Implement a new job worker/src/jobs/abandonedCartReminder.job.ts that:
- Runs every hour (use the same cron registration pattern as
  syncInventory.job.ts)
- Calls cartService.getAbandonedCarts() to find carts with no
  completed order after 24h
- Sends one email per cart via emailService.sendTemplateEmail(),
  using a new template ID "abandoned_cart_reminder"
- Marks the cart as `reminderSentAt` (add this field to the Cart
  model in schema.prisma if it doesn't exist) so we never email
  the same cart twice

Follow existing error handling and logging conventions from
CLAUDE.md. Write a unit test in worker/src/jobs/__tests__/ following
the style of syncInventory.job.test.ts.

Prompt này minh hoạ đúng nguyên tắc cả bài: kết hợp (a) auto-context đã xác nhận scope, (b) manual inclusion các file mẫu cụ thể, (c) tham chiếu ngầm tới CLAUDE.md cho convention chung, và (d) yêu cầu rõ ràng về test — không để AI tự quyết định phạm vi.

Bước 4 — Review diff với con mắt "context đã đủ chưa", không chỉ "code đúng chưa".

Sau khi nhận code, đừng chỉ review logic — kiểm tra xem AI có vô tình bỏ qua gotcha nào trong CLAUDE.md không (ví dụ nếu bạn có ghi chú "Redis job chưa idempotent," hãy chắc chắn code mới có xử lý việc gửi trùng email). Nếu phát hiện AI hiểu sai một convention, đó là tín hiệu để quay lại Bước 1 và bổ sung CLAUDE.md — biến lỗi một lần thành cải thiện lâu dài cho cả team.

Bước 5 — Dọn dẹp context sau khi xong.

Nếu bạn đã thêm ghi chú tạm thời kiểu "TODO: xác nhận với team X" vào CLAUDE.md ở Bước 1, dọn lại cho gọn sau khi merge — CLAUDE.md là tài liệu sống, không phải nhật ký công việc.

Mẹo: Lưu lại các prompt "khám phá trước khi code" (Bước 2) như một pattern có thể tái sử dụng cho mọi feature mới — nó rẻ hơn nhiều so với chi phí phải revert một PR sai hướng.

Những điểm chính

  • AI coding tool dựng context tự động qua ba lớp: file tree, symbol index, và semantic search dựa trên embedding — mỗi lớp đều có thể bỏ sót hoặc hiểu sai, không nên tin tuyệt đối.
  • Manual file inclusion (@file trong Cursor, chỉ định đường dẫn trong Claude Code) chính xác và tiết kiệm token hơn auto-context khi bạn đã biết rõ file liên quan.
  • CLAUDE.md nên đóng vai trò tài liệu vận hành nội bộ — bao gồm Architecture Overview, Repository Structure, Tech Stack, Coding Conventions, Key Files, và đặc biệt là Gotchas — chứ không phải README marketing.
  • .cursorignore là lớp kiểm soát độc lập với .gitignore, cần thiết để chặn AI đọc secret/credential và để tránh lãng phí context vào build artifact hay dependency.
  • Đối chiếu định kỳ giữa .gitignore.cursorignore để tránh hai rủi ro ngược chiều: rò rỉ dữ liệu nhạy cảm, hoặc thiếu context quan trọng cho AI.
  • Workflow hiệu quả khi bắt đầu một feature mới: cập nhật CLAUDE.md nếu thiếu → để AI tự khám phá phạm vi trước khi code → chỉ định manual các file mẫu cần theo → review diff đối chiếu với gotcha đã ghi nhận → cập nhật lại CLAUDE.md nếu phát hiện lỗ hổng.