Tóm tắt — Tụi mình mất cả tháng để viết một series về harness engineering cho Claude Code: Memory, Tools, Permissions, Hooks, Observability. Nhưng phần thời gian còn lại, tụi mình lại đi dựng chính cái harness đó bằng tay, lặp đi lặp lại qua từng project mới — và mỗi đồng đội lại làm hơi khác nhau một chút. Một kỷ luật mà tuần nào cũng phải gõ lại từ đầu thì không phải kỷ luật, nó là việc vặt. Nên tụi mình gói cả series thành một câu lệnh open-source. Bài này kể lý do, kèm link tới từng dòng code.
Một sáng thứ Hai. Repo mới. Thư mục .claude/ trống trơn. Con trỏ nhấp nháy trong một file CLAUDE.md mới tinh.
Và mình làm đúng cái việc đã làm cả chục lần trước đó: mở project tháng trước ở cửa sổ thứ hai và bắt đầu copy. Block permissions. Cái guard chặn rm -rf. Khung MEMORY.md. Config MCP. Cái sườn doc kiến trúc. Tab qua, paste, find-and-replace tên project, tab lại.
Đang làm dở thì cái sự trớ trêu ập đến. Tụi mình vừa publish một series 8 bài dạy dev đúng cái này — cách dựng một harness Claude Code đáng tin, từng tầng một. Vậy mà ở đây, chính người viết ra nó, lại đang làm cái việc thiếu “kỹ thuật” nhất có thể: gõ lại cùng một harness từ trí nhớ, cầu mong đừng quên tầng nào.
Bài này nói về đúng khoảng trống đó, và về thứ tụi mình làm ra để bít nó lại.
Có kỷ luật nhưng không có công cụ
Quay lại ý tưởng cột sống của cả series: Agent = Model + Harness. Model là hàng hoá phổ thông — ai dùng cùng phiên bản Claude thì có cùng năng lực thô. Harness mới là phần của riêng bạn. Đó là lý do một team ship sạch sẽ, còn team bên cạnh thì rollback hết lần này tới lần khác.
Tụi mình tách harness đó thành năm tầng và viết một bài đào sâu cho mỗi tầng:
- Memory — những gì agent biết trước cả khi bạn gõ. Tụi mình lập luận rằng CLAUDE.md nên là một nhật ký lỗi, không phải một danh sách ước, và bạn cần một MEMORY.md để khỏi phải giải thích lại vụ migration tuần trước.
- Tools — những gì agent với tới được, thông qua MCP server.
- Permissions — những gì agent được phép đụng vào. Tụi mình đã chỉ cách ba mươi giây config chặn một lệnh install bất cẩn khỏi phá nát máy bạn.
- Hooks — thứ được enforce ngay lúc chạy, tầng duy nhất mà context không cãi lại được. Tụi mình làm hẳn một bộ guide chọn hook bạn thực sự cần.
- Observability — những gì bạn nhìn lại được sau đó, gồm cả một vòng tự kiểm tra bắt agent tự soát việc của mình trước khi tuyên bố “xong rồi”.
Và nằm dưới tất cả là nghịch lý ràng buộc: càng siết những gì agent được làm, nó càng làm tốt những gì nên làm. Team LangChain cũng đã công khai chứng minh điều tương tự: chính thay đổi ở harness và context, chứ không phải bản thân model, đã tạo ra cú nhảy +13.7 điểm (52.8% → 66.5%) trên Terminal Bench 2.0 — cùng một model, harness tốt hơn (LangChain Blog, Feb 2026).
Lý thuyết ngon. Bằng chứng thật. Mà bài nào cũng kết thúc y hệt nhau: “copy block này vào thư mục .claude/ của bạn.”
Đó là vấn đề nằm phơi ngay trước mắt. Tụi mình viết một cuốn cẩm nang đẹp đẽ cho một nhà máy, rồi bảo mọi người tự ráp dây chuyền bằng tay, từng con bu-lông một, trong mỗi toà nhà mới. Một quy trình (SOP) mà lần nào cũng phải làm thủ công thì không phải hệ thống. Đó là một bài kiểm tra trí nhớ mà sớm muộn bạn cũng trượt.
Hai kiểu hỏng ít ai cảnh báo bạn
Khi dựng harness bằng tay, có hai thứ hỏng — một cách âm thầm.
Bạn quên một tầng. Không phải mấy tầng nổi tiếng đâu. Hook rm -rf thì bạn luôn nhớ, vì nó từng làm bạn hú hồn một lần. Bạn quên cái tầng nhàm chán kia — cái log observability, cái index MEMORY.md — và bạn không nhận ra cho tới ba tuần sau, khi agent tự tin tái tạo lại một con bug bạn đã fix trong một session mà nó chẳng còn lưu vết.
Team bạn lệch pha trước cả khi project bắt đầu. Một dev viết block permissions chặt. Người khác copy một bản cũ, lỏng hơn. Người thứ ba bỏ luôn hooks “tạm thời thôi mà”. Giờ bạn không có một harness — bạn có bốn phương ngữ của cùng một harness. Cả cái lý do để commit harness vào version control là để cả team thừa hưởng cùng độ tin cậy. Ráp tay phá tan điều đó ngay ngày đầu.
Cách sửa không phải là một model thông minh hơn; tụi mình đã viết hẳn một bài để nói ý này. Cách sửa là biến harness đúng thành harness dễ: tái lập được, giống hệt nhau, và nhàm chán khi set up.
Nên tụi mình gói cả series thành một câu lệnh
Tụi mình lấy từng bài bạn vừa đọc và tự hỏi: nếu nó không phải là một block code để copy, mà là một câu hỏi trong buổi phỏng vấn thì sao?
Đó là shipwithai-starter. Một plugin open-source. Bạn chạy:
/shipwithai-starter:initNó hỏi về stack của bạn và bạn muốn chặt chẽ tới mức nào, rồi viết luôn cả harness cho bạn — đúng năm tầng trong series, cộng thêm hai tầng tụi mình học được dọc đường (nói thêm ở dưới). Năm phút cho phần cốt lõi, ba mươi phút cho bản đầy đủ. Sau đó:
git add CLAUDE.md .claude/ .mcp.json docs/git commit -m "chore: add Claude Code harness"Đồng đội của bạn clone repo về, mở Claude Code, và harness đã nằm sẵn ở đó. Không cần cửa sổ thứ hai. Không find-and-replace. Không lệch pha. Dây chuyền sản xuất đi kèm sẵn trong toà nhà.
Giờ mỗi bài trong series đều có một câu lệnh tương ứng ở phía bên kia:
| Bạn đã đọc | Giờ bạn chạy được |
|---|---|
| Vá MEMORY.md · CLAUDE.md kiểu nhật ký lỗi | /setup-memory |
| Hướng dẫn setup MCP | /setup-mcp |
| Bảo mật install trong 30 giây | /setup-permissions |
| Chọn hook nào cho đúng | /setup-hooks |
| Vòng tự kiểm tra | /setup-observability |
Blog vẫn dạy bạn làm bằng tay — và bạn nên đọc, vì bạn không thể bảo trì thứ mình không hiểu. Plugin chỉ giúp bạn làm bằng tay một lần, để học, thay vì mỗi thứ Hai, mãi mãi.
Hai tầng tụi mình chưa viết (vẫn chưa)
Đây là phần thành thật. Series nói năm tầng. Plugin set up bảy.
Không phải gõ nhầm đâu — đó là cái mà dogfooding làm với một framework. Khi bạn thật sự dựng lại harness qua cả chục project thật, có thêm hai thứ hoá ra đáng được tách riêng thành một tầng:
- Agents — các sub-agent chuyên biệt trong
.claude/agents/, gồm mộtdrift-monitorchạy hàng tuần và báo cho bạn biết khi CLAUDE.md đã âm thầm không còn khớp với code nữa. Đó chính là mẫu nhật-ký-lỗi, được tự động hoá: thay vì nhớ phải cập nhật ràng buộc, harness tự nhận ra giùm bạn. - SSOT — tài liệu nguồn-chân-lý-duy-nhất: một file kiến trúc, các Architecture Decision Record, bản đồ codebase. Phần context giữ cho agent khỏi đem ra cãi lại những quyết định bạn đã chốt.
Tụi mình sẽ viết bài đào sâu cho cả hai. Nhưng thà ship cái tool đang chạy được và nói thật với bạn — framework lớn lên vì tụi mình đã dùng nó — còn hơn giả vờ rằng tấm bản đồ đã hoàn hảo trước khi đặt chân lên thực địa. Đó là toàn bộ tinh thần ở đây: thử trong repo của chính mình trước, chia sẻ sau.
Đọc từng dòng trước khi chạy
Plugin open-source hoàn toàn: github.com/ShipWithAI/shipwithai-plugins.
Tụi mình nói hoàn toàn là thật. Mấy cái hook chặn lệnh phá hoại, logic phỏng vấn, các template nó viết vào project của bạn, con agent drift-monitor — tất cả nằm trong repo, dưới dạng Markdown và Python thuần mà bạn đọc hết trong một buổi chiều. Thà bạn tự soi cái thứ sắp ghi vào thư mục .claude/ của mình, còn hơn tin tụi mình bằng niềm tin. Đó là cách trung thực duy nhất để ship một công cụ mà nhiệm vụ của nó chính là enforce ràng buộc.
Nếu bạn đã đọc dù chỉ một bài trong series, bạn đã hiểu hết những gì plugin làm. Nó không phải phép màu. Nó là series, được biến thành thứ chạy được.
Bắt đầu từ đâu
Nếu bạn mới đến, đọc bài 5 tầng trước — hiểu các tầng đã, rồi mới tự động hoá. Nếu bạn đã có sẵn CLAUDE.md và đang chán cảnh gõ lại nó, nhảy thẳng tới repo.
Đằng nào thì bài kiểm tra cũng vẫn là cái mình đã trượt sáng thứ Hai đó: mở một repo mới sáu tháng sau. Nếu bạn bắt gặp mình đang copy harness từ một project cũ bằng tay, thì công cụ đã thua. Nếu harness đã nằm sẵn ở đó vì một câu lệnh và một commit đặt nó vào — đó là lúc harness engineering cuối cùng cũng tự “engineer” chính nó.
Tụi mình viết tám bài về cái kỷ luật này. Đây là bài thứ chín, và là bài tụi mình ngừng thực hành nó bằng tay.
Tới lượt bạn: Clone repo, chạy
/shipwithai-starter:inittrên một project thật, commit kết quả, rồi nhờ một đồng đội pull về. Lần đầu tiên thấy harness của người khác hiện ra giống hệt của bạn mà không cần set up gì, bạn sẽ cảm nhận được đúng điều mà cả series này đang muốn chỉ tới.
shipwithai-starter được team ShipWithAI xây và bảo trì. Tụi mình dùng nó trong repo của chính mình trước khi khuyên bạn dùng trong repo của bạn.