Vibe code app tìm tiếng bíp bằng Claude Code: 7 bài học
Simon Willison nhờ Claude Code biến điện thoại, laptop thành dàn micro tìm tiếng bíp bí ẩn. Cách app hoạt động, quy trình 4 giai đoạn và 7 bài học vibe code.

Trong bài này
- 14 phút đọc
- 10 phần
- 3 mẫu sao chép được
Cách bài viết này được thực hiện: bài dựa trên hai bài blog ngày 9/11/2026 của Simon Willison (nhà phát triển, đồng tác giả framework Django) và README của dự án mã nguồn mở Beep Locator trên GitHub, kiểm tra ngày 13/11/2026. Mmo.vn chưa tự dựng lại toàn bộ hệ thống; các lệnh cài đặt lấy từ README chính thức và tài liệu của công cụ.
Trong nhà bạn có thứ gì đó kêu “bíp” một tiếng, rồi im lặng rất lâu mới kêu tiếp. Bạn đi lòng vòng, áp tai vào từng góc mà vẫn không biết nó ở đâu. Simon Willison gặp đúng tình huống đó trong căn phòng chất đầy thùng đồ sau khi chuyển nhà. Thay vì lục tung từng thùng, ông nhờ Claude Code viết một ứng dụng biến điện thoại, máy tính bảng và laptop trong nhà thành dàn micro để “định vị” tiếng bíp.
Kết quả: ứng dụng khoanh vùng nguồn âm trong khoảng 40 cm, và thủ phạm là một máy báo khí CO cũ cần thay pin. Câu chuyện nghe vui, nhưng cách ông làm việc với agent là một bài học vibe code rất thực tế. Bài này kể lại dự án, giải thích ứng dụng hoạt động thế nào, rút ra bảy bài học bạn áp dụng được ngay, kèm mẹo trình bày pull request do AI viết.
Câu trả lời ngắn: Simon Willison dùng Claude Code viết Beep Locator, ứng dụng web dùng nhiều thiết bị làm micro, đo độ lệch thời gian tiếng bíp tới từng máy để tìm vị trí. Bí quyết không nằm ở prompt mà ở quy trình: viết problem.md mô tả vấn đề, để agent tìm nghiên cứu, rồi cho agent chạy và “nghe” kết quả để tự sửa.
Tóm tắt nhanh
- Dự án: Beep Locator, mã nguồn mở giấy phép Apache 2.0, chạy trên trình duyệt với server Python.
- Thiết bị nghe: 2 iPad, 1 điện thoại, 1 MacBook Pro, 1 Surface Ultra.
- Kết quả: định vị trong khoảng 40 cm, tìm ra máy báo khí CO hết pin.
- Mô hình: lên kế hoạch bằng Opus 5.5 trên điện thoại, thử trực tiếp bằng Fable 5.2 trên laptop.
- Mẹo kèm theo: giấu phần mô tả PR dài do AI viết trong thẻ details/summary.
Nội dung chính:
- Chuyện gì đã xảy ra
- Beep Locator hoạt động thế nào
- Quy trình làm việc với Claude Code
- Cho agent “đôi tai”: vòng phản hồi
- Bảy bài học vibe code
- Mẹo trình bày pull request do AI viết
- Tự chạy thử Beep Locator
- Hiểu lầm phổ biến
- Câu hỏi thường gặp
- Kết luận
Chuyện gì đã xảy ra
Sau khi chuyển nhà, gia đình Simon Willison dồn thùng đồ vào một căn phòng nhỏ. Rồi một ngày, thứ gì đó trong phòng bắt đầu kêu bíp, thưa thớt, cách nhau rất lâu. Tìm bằng tay nghĩa là mở từng thùng, việc ông muốn tránh.
Ông nảy ra ý dùng chính các thiết bị trong nhà làm micro: hai chiếc iPad, một điện thoại, một MacBook Pro và một Surface Ultra. Nếu biết vị trí từng máy và thời điểm tiếng bíp tới mỗi máy, ta có thể tính ra nguồn âm nằm ở đâu, giống cách nhiều micro cùng “nghe” để định vị. Ông giao việc viết phần mềm cho Claude Code, và đặt tên dự án là Beep Locator.
Hệ thống khoanh vùng tiếng bíp trong khoảng 40 cm. Nguồn âm hoá ra là một máy báo khí carbon monoxide (CO) cũ cần thay pin. Một kết thúc rất đời thường cho một dự án nghe như phim khoa học viễn tưởng.


Beep Locator hoạt động thế nào
Theo bài blog và README, Beep Locator gồm một server Python điều phối và các “máy nghe” là trình duyệt trên điện thoại, máy tính bảng, laptop. Máy nghe kết nối với server qua WebSocket và lấy âm thanh từ micro bằng WebAudio của trình duyệt.
- Bộ đệm 60 giây: mỗi máy nghe luôn giữ 60 giây âm thanh gần nhất, nên khi có tiếng bíp, dữ liệu ngay trước đó vẫn còn.
- Phát hiện tiếng bíp: file
detector.jsdùng biến đổi Fourier nhanh (FFT) và bộ lọc thông cao để nhận ra âm thanh có thể là tiếng bíp. - Đồng bộ bằng tiếng chirp: khi có máy báo tiếng bíp, server yêu cầu thiết bị có độ trễ mạng thấp nhất phát một tiếng “chirp” ngắn. Mọi máy gửi lên đoạn âm thanh từ khoảng 0,6 giây trước đến 0,8 giây sau tiếng chirp. Tiếng chirp làm mốc để căn thời gian các đoạn ghi.
- Đo khoảng cách giữa các máy: các thiết bị phát chirp cho nhau nghe (đo khoảng cách âm thanh hai chiều) để tự tìm vị trí tương đối, sau đó dùng độ lệch thời gian tiếng bíp tới từng máy để ước lượng nguồn âm.
Kỹ thuật đo khoảng cách bằng âm thanh trên thiết bị phổ thông không phải mới. Claude tự tìm ra bài báo khoa học BeepBeep công bố tại hội nghị SenSys năm 2007 (nhóm tác giả Chunyi Peng, Guobin Shen, Yongguang Zhang, Yanlin Li, Kun Tan), mô tả cách đo khoảng cách chỉ bằng phần mềm, dùng loa và micro có sẵn. Willison nhận xét nó nghe đúng là thứ ông cần.

Quy trình làm việc với Claude Code
Điều đáng học nhất là cách Willison chia dự án thành các giai đoạn, mỗi giai đoạn dùng Claude Code ở một nơi khác nhau.
Giai đoạn 1: Lên kế hoạch trên điện thoại
Ông mở Claude Code bản chạy trên cloud từ iPhone, chọn Opus 5.5 với mức suy nghĩ “Extra thinking”. Prompt đầu tiên không bảo viết code, mà bảo Claude viết file problem.md mô tả vấn đề cho một repo GitHub còn trống. Từ đó Claude đi tìm và đọc bài báo BeepBeep.
Giai đoạn 2: Dựng phần lớn hệ thống
Tiếp theo, ông yêu cầu Claude xây hệ thống và thêm cách đẩy code mới tới các máy nghe để chúng tự chạy. Ở giai đoạn này, phần lớn hệ thống đã được viết nhưng chưa từng chạy thật.
Giai đoạn 3: Thử trực tiếp trên laptop
Ông chuyển sang Claude Code trên laptop, dùng Fable 5.2, mô hình Anthropic ra mắt đúng lúc dự án đang làm (xem bài Claude Fable 5.2 cho lập trình viên). Lúc này Claude tự chạy server, nhìn được output của hệ thống và sửa phần mềm ngay khi nó đang chạy.
Giai đoạn 4: Thêm tính năng bằng các prompt nhỏ
Sau khi chạy được, ông thêm từng tính năng qua prompt ngắn: chế độ kéo thả vị trí thiết bị gần đúng, nhận diện tiếng vỗ tay để thử nghiệm (hiện thành hình thoi, tiếng bíp là dấu X), dấu thời gian, nút phát lại đoạn ghi, nút xác nhận “đây là tiếng bíp bí ẩn”, di chuyển thiết bị mà không phải khởi động lại, và gợi ý chỗ nên đặt thêm máy nghe.

Cho agent “đôi tai”: vòng phản hồi
Claude không có tai. Nhưng Willison mô tả dự án là “giving Claude Code ears”, tức trao cho Claude Code đôi tai. Cách làm: Claude chạy code JavaScript và Python xử lý dữ liệu micro, nên nó phân tích được âm thanh, truy vấn nhật ký và tự cấu hình lại các máy nghe.
Mấu chốt kỹ thuật là hàm installModule() mà Opus 5.5 viết từ giai đoạn trước. Hàm này cho server gửi code mới tới bất kỳ máy nghe nào qua WebSocket. Nhờ vậy không cần tải lại trang, tránh việc một số trình duyệt bắt cấp lại quyền micro sau mỗi lần tải lại. Mỗi lần Claude sửa thuật toán, các máy nghe nhận code mới ngay, Claude thử lại và đọc kết quả.
Willison so sánh với cách Martin Woodward gỡ lỗi máy tính trên huy hiệu GitHub Universe bằng cách chĩa webcam vào màn hình để agent “nhìn” thấy kết quả. Ý chung: agent làm tốt nhất khi tự thấy hậu quả của code mình viết, không phải chờ người mô tả lại.

Bảy bài học vibe code
1. Bắt đầu bằng file mô tả vấn đề
Thay vì “viết cho tôi app tìm tiếng bíp”, hãy để agent viết problem.md: bối cảnh, ràng buộc, thiết bị có sẵn, kết quả mong muốn. File này thành điểm tựa cho mọi phiên sau. Một mẫu đơn giản:
# Vấn đề
Phòng chứa đồ có tiếng bíp ngắt quãng, không rõ nguồn.
# Thiết bị có sẵn
2 iPad, 1 iPhone, 1 MacBook, 1 laptop Windows. Cùng mạng wifi.
# Mục tiêu
Ứng dụng web: mỗi thiết bị mở một đường link để làm máy nghe.
Bản đồ hiện vị trí ước lượng của tiếng bíp, sai số dưới 1 m.
# Ràng buộc
Không cài app; chạy trên trình duyệt. Server viết bằng Python.
# Việc trước tiên
Tìm nghiên cứu về đo khoảng cách bằng âm thanh trên thiết bị phổ thông.
Mỗi tiêu đề trả lời một câu hỏi agent sẽ cần: đang giải quyết gì, có gì trong tay, thế nào là xong, cái gì không được làm, và bắt đầu từ đâu.
2. Để agent nghiên cứu trước khi code
Claude tìm ra bài báo BeepBeep trước khi viết dòng code nào. Với bài toán bạn chưa rành, hãy yêu cầu agent tìm cách người khác đã giải, tóm tắt và đề xuất hướng làm.
3. Chọn mô hình theo giai đoạn
Willison dùng Opus 5.5 với mức suy nghĩ cao cho phần thiết kế, Fable 5.2 cho phần thử và sửa trực tiếp. Bạn không bắt buộc làm giống, nhưng nên nghĩ: giai đoạn nào cần suy nghĩ sâu, giai đoạn nào cần phản hồi nhanh.
4. Cho agent thấy kết quả chạy
Đây là bài học quan trọng nhất. Agent chỉ đọc được code thì đoán; agent chạy được server, đọc log, xem output thì sửa có căn cứ.
5. Thiết kế để cập nhật nóng
Nếu mỗi lần sửa phải làm thủ công nhiều bước (tải lại năm thiết bị, cấp lại quyền micro), vòng lặp sẽ chậm. Một cơ chế như installModule() rút vòng lặp xuống vài giây.
6. Thêm tính năng bằng prompt nhỏ
Sau khi phần lõi chạy, mỗi prompt chỉ thêm một thứ: nút phát lại, dấu thời gian, gợi ý vị trí. Prompt nhỏ dễ kiểm tra và dễ quay lại khi hỏng.
7. Giữ ngữ cảnh trong repo
Repo Beep Locator có cả problem.md và CLAUDE.md. Thông tin quan trọng nằm trong file, không chỉ nằm trong lịch sử chat, nên phiên mới hoặc agent khác vẫn tiếp tục được.

Mẹo trình bày pull request do AI viết
Cùng ngày, Willison chia sẻ thêm một thói quen nhỏ. Phần lớn thay đổi trong các dự án của ông giờ đến từ pull request (PR) do Claude Code và Codex mở. Mô tả PR do agent viết thường chính xác và đầy đủ, nhưng đọc rất mệt. Phản ứng thật của ông với chữ do AI viết là “tôi không đọc hết đâu”.
Cách ông xử lý: tự viết một đoạn mở đầu ngắn, đôi khi kèm ảnh chụp màn hình, nói PR này để làm gì. Toàn bộ mô tả của agent được giấu trong khối <details><summary> mà Markdown của GitHub hỗ trợ, với dòng tóm tắt là tên mô hình và thường kèm mức effort, ví dụ “Claude Opus 5.5 Medium”. Mẫu bạn có thể dùng:
Thêm thanh phân trang ở đầu và cuối bảng để người xem biết đang ở trang nào.
Claude Opus 5.5 Medium
(Dán toàn bộ mô tả do agent viết vào đây.)
Lưu ý phải có một dòng trống sau thẻ <summary> và trước </details> để GitHub hiển thị đúng Markdown bên trong. Thẻ details bọc ngoài, summary là dòng bấm để mở. Willison gợi ý đọc to “details-summary” để nhớ thứ tự. Người xem PR nắm ý chính trong một câu, ai cần chi tiết thì bấm mở.


Tự chạy thử Beep Locator
Beep Locator là mã nguồn mở giấy phép Apache 2.0, README ghi rõ phần mềm do Claude viết. Nếu muốn thử, bạn cần:
- uv: trình quản lý dự án Python. Windows cài bằng PowerShell:
powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex". - cloudflared: tạo đường hầm HTTPS, vì điện thoại chỉ cho trang web dùng micro khi chạy qua HTTPS. macOS:
brew install cloudflared; Windows:winget install --id Cloudflare.cloudflared. - Từ 3 thiết bị nghe trở lên: bật âm lượng, tắt chế độ im lặng, không dùng loa Bluetooth, cắm sạc và để màn hình sáng.
Rồi chạy ba lệnh từ README:
git clone https://github.com/simonw/beep-locator
cd beep-locator
uv run beep-locator serve --tunnel
Lệnh đầu tải mã nguồn về, lệnh hai vào thư mục dự án, lệnh ba để uv tự cài thư viện và chạy server kèm đường hầm HTTPS. Server in ra một đường link điều phối (mở trên laptop) và một đường link kèm mã QR để từng điện thoại, máy tính bảng tham gia. Sau đó: đặt các máy quanh phòng, bấm Calibrate để hiệu chỉnh, dùng xoay hoặc lật để bản đồ khớp với phòng, thử bằng Test beep, rồi bật Listen for beeps.
Chưa có đủ thiết bị? README có chế độ phòng giả lập: mở đường dẫn /sim?n=5&every=10&bx=3&by=2 trên địa chỉ server. Repo cũng có bộ test chạy bằng uv run pytest, một nơi tốt để xem agent đã viết test thế nào.

Hiểu lầm phổ biến
“Vibe code là gõ một câu rồi có app.” Dự án này trải qua nhiều phiên, nhiều mô hình và hàng loạt prompt nhỏ. Phần “vibe” là bạn không tự gõ code, không phải là không có quy trình.
“Agent chỉ làm được việc nó có công cụ sẵn.” Claude không có đầu vào âm thanh, nhưng tự viết code để xử lý micro và đọc kết quả. Thiết kế đúng vòng phản hồi có thể mở rộng khả năng của agent.
“Mô hình mạnh nhất cho mọi việc là tốt nhất.” Willison dùng mô hình khác nhau cho giai đoạn khác nhau. Cái cần là đúng việc, không phải luôn chọn mức cao nhất.
“Mô tả PR càng dài càng chuyên nghiệp.” Người đọc cần ý chính trước. Chi tiết vẫn nên có, nhưng để người cần thì mở.

Câu hỏi thường gặp
Beep Locator có dùng được ở nhà mình không?
Có thể, nếu bạn có ít nhất 3 thiết bị có micro và trình duyệt, cùng máy tính cài được uv và cloudflared. Đây là dự án cá nhân, độ chính xác phụ thuộc phòng, tiếng vang và thiết bị; ngay trong ảnh chụp, ứng dụng cũng cảnh báo một số đoạn có thời gian tới “không khả thi về vật lý” do tiếng vang hoặc âm khác.
Có cần biết xử lý tín hiệu số mới làm được dự án kiểu này?
Willison để Claude tìm và đọc nghiên cứu, rồi viết thuật toán. Bạn không cần là chuyên gia, nhưng cần đủ hiểu để kiểm tra kết quả: thử bằng tiếng vỗ tay ở vị trí đã biết, xem bản đồ có đúng không.
Claude Code chạy trên điện thoại được à?
Willison dùng Claude Code bản chạy trên cloud, mở từ iPhone, để lên kế hoạch và viết phần đầu. Phần cần chạy server, kết nối thiết bị trong nhà thì ông chuyển sang Claude Code trên laptop.
Mẹo details-summary dùng được ở GitLab hay Gitea không?
Thẻ details là HTML chuẩn và nhiều nền tảng hỗ trợ trong Markdown. Bài gốc chỉ nói về GitHub, nên bạn hãy thử xem trước trên nền tảng của mình.
Có nên để agent tự mở pull request?
Willison coi PR là đơn vị công việc: gom commit, lặp tới khi tính năng xong, ghi lại quyết định rồi mới merge. Người vẫn là bên đọc, viết đoạn mở đầu và bấm merge.
Kết luận
Beep Locator là ví dụ đẹp cho kiểu vibe code có phương pháp: viết rõ vấn đề, để agent nghiên cứu, chia giai đoạn, và quan trọng nhất là cho agent thấy kết quả code mình chạy. Một máy báo khí CO hết pin là phần thưởng nhỏ; bài học lớn là cách thiết kế vòng phản hồi để agent tự sửa. Kèm theo đó, mẹo details-summary giúp PR do AI viết dễ đọc hơn hẳn mà không mất thông tin.
Nếu bạn thích kiểu case study này, mmo.vn có thêm bài tự viết app biến podcast YouTube thành ghi chú Obsidian và mẹo prompt Claude Fable 5.2 khi code. Bạn từng dùng AI để giải quyết rắc rối “đời thường” nào chưa? Kể cho mmo.vn ở phần bình luận nhé.
Nguồn tham khảo: Simon Willison, “Locating the source of a mysterious beep with Claude” và “Hide your slop PR descriptions behind details-summary” (simonwillison.net, 9/11/2026); README dự án simonw/beep-locator trên GitHub; bài báo BeepBeep, SenSys 2007.


