cli_.
Phiếu lệnh triển khai · TÔM Voice · app chạy tại máy
Bấm micro trong một nhóm Lark riêng và nói một câu. Máy bạn nghe, giao việc cho Claude Code, rồi đọc kết quả trả lại bằng giọng Việt — gắn ngay dưới tin bạn vừa nói. Điền 2 ô, sao chép khối lệnh, dán vào Claude Code; phần còn lại nó tự dò và tự dựng.
Đây là app thường trú chạy tại máy bạn: tải repo về, cài một lần, rồi bật. Cấu hình nằm ngay trên máy ở scripts/.env. Đóng cửa sổ hoặc tắt máy là TÔM ngủ — không có ai chạy thay.
| Câu hỏi | Trả lời |
|---|---|
| Chạy ở đâu | Máy của bạn — không phải máy chủ nào trên mạng |
| Phải fork repo? | Không — chỉ tải về rồi chạy |
| Phải nạp Secrets ở đâu đó? | Không — mọi cấu hình nằm ở scripts/.env trên máy bạn |
| Máy tắt thì sao | TÔM ngủ cho tới khi bạn bật lại |
| Kích hoạt bằng gì | Bạn nói — hoặc gõ — một câu vào nhóm điều khiển |
| Trả lời về đâu | Gắn thẳng vào tin của bạn — nói thì nghe giọng, gõ thì đọc chữ |
| Ai ra lệnh được | Chỉ bạn, và chỉ trong nhóm điều khiển — người khác nhắn vào, TÔM lờ đi |
PERMISSION_MODE=bypassPermissions là mặc định của gói.Nghĩa là TÔM chạy thẳng lệnh trên máy mà không hỏi bạn từng bước — đọc, sửa, xoá file, gọi lệnh hệ thống, trong phạm vi BRAIN_ROOT bạn chỉ định. Đổi lại sự tiện, bạn đang giao chìa khoá. Chỉ bật trên máy riêng của bạn, đừng bật trên máy chung hay máy công ty. Và BRAIN_ROOT chỉ nên trỏ vào thư mục bạn thật sự chấp nhận cho AI sửa.
Khoảng 10 phút, làm một lần. Claude Code không làm hộ được phần này — nó nằm trong tài khoản Lark của bạn.
open.larksuite.com (bản .cn: open.feishu.cn) → Developer Console → Create Custom App → Add features → Bot.
im:message — nhận tinim:message:send_as_bot — gửi tin thay botim:resource — tải/gửi file, ảnh, audio. Thiếu đúng dòng này thì chữ vẫn chạy nhưng giọng nói hỏng câm — nghe không được, đọc trả lời cũng không gửi đi được.Chọn chế độ Long Connection (khỏi cần URL công khai, khỏi cần ngrok), rồi subscribe event im.message.receive_v1.
Version Management & Release → Create version → Publish. Bản nháp chưa publish thì event và scope chưa có hiệu lực: bạn nhắn vào nhóm mà whoami.mjs im lặng không in gì, và không có cách nào đoán ra nếu không biết trước.
Mục Credentials & Basic Info. App ID có dạng cli_… — lát nữa điền vào ô ở mục 04. App Secret chỉ dùng để đăng nhập lark-cli, không ghi vào repo, không ghi vào .env.
Tạo 1 nhóm Lark riêng (chỉ mình bạn cũng được) → Add members → thêm Bot của app vừa tạo. Đây là nhóm duy nhất TÔM lắng nghe. Quên bước thêm bot là mọi thứ khác đúng mà vẫn không chạy.
lark-cli bằng chính app nàyCài npm i -g @larksuite/cli rồi đăng nhập app (chọn brand lark cho larksuite.com, feishu cho .cn). Kiểm bằng:
lark-cli profile list # phải thấy app của bạn "active": true
im:resource → gửi/nhận audio hỏng; (3) mỗi app có open_id riêng cho cùng một người — đổi sang app khác là phải chạy lại whoami.mjs lấy lại OWNER_OPEN_ID, giá trị cũ vô dụng.
| Cần có | Kiểm bằng | Chưa có thì cài |
|---|---|---|
| Node.js ≥ 18 | node -v | Tải bản LTS ở nodejs.org |
| Python 3.10–3.12 | uv --version python --version | Gọn nhất là cài uv (nó tự tải Python):powershell -c "irm https://astral.sh/uv/install.ps1 | iex" |
| ffmpeg | ffmpeg -version | winget install Gyan.FFmpeg → mở PowerShell mới rồi kiểm lại |
| lark-cli | lark-cli --version | npm i -g @larksuite/cli |
| claude | claude --version | Cài Claude Code CLI và đăng nhập trên máy này |
python? Rất hay gặp — cái python gõ ra chỉ là stub của Microsoft Store. Đừng vật lộn với nó: cài uv, install.ps1 ưu tiên dùng uv và tự trỏ PYTHON_BIN vào .venv riêng của gói.
nvidia-smi rồi tự chốt WHISPER_MODEL — có GPU thì medium, không thì small. Nó sẽ báo lại kết quả cho bạn. Có GPU thì hai gói này là bắt buộc: install.ps1 tự cài nvidia-cublas-cu12 + nvidia-cudnn-cu12 khi thấy nvidia-smi. Thiếu chúng, Whisper vẫn nạp được lên GPU nhưng suy luận lỗi ngầm → bot trả “❌ Nghe không rõ” với mọi câu bạn nói, mà không báo lỗi gì rõ ràng. Đây là sự cố tốn thời gian nhất của gói này.
cli_.
.env. Nên bỏ trống ô này và tự dán khi lark-cli hỏi — khối lệnh sẽ ghi đúng như vậy.
VOICE_CODE trong .env.
.env không cần cài lại gì.
docs/02-tao-app-lark.md trước khi đi tiếp.
OWNER_OPEN_ID và CONTROL_CHAT_ID — chạy node scripts/whoami.mjs, nhắn một tin bất kỳ vào nhóm điều khiển là nó in ra sẵn 2 dòng; và máy có GPU NVIDIA hay không — Claude Code tự chạy nvidia-smi rồi tự chốt WHISPER_MODEL. Khối lệnh đã ôm trọn cả ba.
Chưa điền ô nào — khối lệnh đang ở dạng mẫu.
git clone repo về. Lưu ý nhánh mặc định của repo là master, không phải main — tải zip nhầm nhánh sẽ ra trang 404.
start.ps1 mở ra một tiến trình thường trú có toàn quyền chạy lệnh trên máy — thứ đó phải do tay bạn bật, sau khi cổng chốt đã xanh hết. Nếu Claude tự chạy giúp, bạn mất mất cái khoảnh khắc nhìn thấy nó đang chạy bằng quyền gì.
im:resourceTin gõ chữ đi cùng đường nhưng bỏ qua bước nghe và bước đọc — trả lời bằng chữ. Tin thoại thì trả lời bằng giọng.
| Tệp trong repo | Việc của nó |
|---|---|
| scripts/lark-voice-bridge.mjs | Trái tim — nghe Lark, điều phối STT/Claude/TTS, nhớ bối cảnh qua lần khởi động lại |
| scripts/whisper-server.py | Server nghe thường trú (faster-whisper). Có bước warmup: GPU lỗi thì tự lùi CPU thay vì chết |
| scripts/text_to_mp3.py | Đọc trả lời bằng edge-tts (miễn phí). Muốn giọng trả phí thì đổi sang text_to_mp3_vbee.py |
| scripts/whoami.mjs | In ra OWNER_OPEN_ID + CONTROL_CHAT_ID khi bạn nhắn thử |
| scripts/check-setup.mjs | Cổng chốt môi trường — 10 dòng phải ✔ hết |
| scripts/start.ps1 | Nút bật. Thuần ASCII — thêm dấu tiếng Việt vào là cửa sổ tắt phụt |
| scripts/watchdog.mjs | Tuỳ chọn 24/7 — 3 phút kiểm một lần, bridge chết hoặc treo thì bật lại |
| check-itto.mjs | Cổng chốt gói — đủ mảnh chưa, chạy ở thư mục gốc repo |
node check-itto.mjs # gói đủ mảnh chưa node scripts/check-setup.mjs # môi trường + Lark + .env sẵn sàng chưa
check-setup.mjs soát đúng 10 mắt xích. Còn một dòng đỏ là chưa bật bridge:
.env tồn tại — chưa có thì chạy lại install.ps1OWNER_OPEN_ID đã điền — lấy bằng whoami.mjsCONTROL_CHAT_ID đã điền — lấy bằng whoami.mjsPYTHON_BINfaster-whisper + edge-tts + dotenvffmpeg trên PATHlark-cli có mặtlark-cli có profile active: true — tức là đã đăng nhập app của bạnclaude có mặtwhoami.mjs rồi nhắn một tin: im lặng không in gì = một trong hai việc đó chưa xong.
powershell -ExecutionPolicy Bypass -File scripts/start.ps1
Chờ tới khi cửa sổ hiện đủ hai dòng: ✅ Bridge sẵn sàng. và ✅ whisper STT sẵn sàng. Lần đầu Whisper phải tải model — small mất vài chục giây, medium mất 1–2 phút. Đừng nói gì trước khi thấy dòng thứ hai.
Vào nhóm điều khiển, bấm micro và nói — hoặc gõ chữ cũng được. Trả lời sẽ gắn vào đúng tin của bạn. Lệnh nhanh gõ trong nhóm: /ping (bridge còn sống không) · /voice on|off · /reset (phiên Claude mới) · /forget (xoá sạch nhớ đệm) · /mem · /id · /help.
Shortcut trỏ tới đường mạng \\máy\thư-mục\… sẽ bị Windows chặn ngầm khi double-click: không báo lỗi, không mở gì, bạn tưởng hỏng file. Trỏ vào đường nội bộ ổ C:.
$ps1 = "C:\<đường-dẫn-repo>\scripts\start.ps1"
$lnk = "$([Environment]::GetFolderPath('Desktop'))\TOM Voice.lnk"
$w = New-Object -ComObject WScript.Shell
$s = $w.CreateShortcut($lnk)
$s.TargetPath = "$env:SystemRoot\System32\WindowsPowerShell\v1.0\powershell.exe"
$s.Arguments = "-ExecutionPolicy Bypass -NoProfile -File `"$ps1`""
$s.WorkingDirectory = (Split-Path $ps1)
$s.IconLocation = "shell32.dll,138"
$s.Save()
Đăng ký watchdog.mjs vào Windows Scheduled Task (xem docs/04-chay-va-24-7.md): 3 phút kiểm một lần, bridge chết hoặc tim ngừng đập thì tự bật lại. Điền LARK_WEBHOOK vào .env để nó báo về Lark mỗi lần khởi động lại.
Nhưng: 24/7 + bypassPermissions nghĩa là có một AI toàn quyền chạy lệnh trên máy bạn không giám sát, kể cả lúc bạn ngủ. Bật chế độ này chỉ khi bạn thật sự cần và hiểu mình đang đánh đổi cái gì.
DRY_RUN=true trong .env → bridge vẫn nhận tin, vẫn nghe, vẫn đọc, nhưng không gọi Claude thật (chỉ vọng lại). Dùng để dò luồng Lark và giọng nói mà không tốn đồng nào.
| Hiện tượng | Nguyên nhân thật & cách sửa |
|---|---|
Double-click start.ps1 → cửa sổ tắt phụt | File .ps1 có dấu tiếng Việt. PowerShell 5.1 đọc .ps1 theo bảng mã ANSI chứ không phải UTF-8 → vỡ cú pháp. Bản trong gói đã thuần ASCII; nếu tự sửa thì giữ nguyên ASCII. |
| Shortcut Desktop mở không được | Shortcut trỏ đường mạng UNC (\\…) — Windows chặn ngầm ở Explorer. Trỏ lại vào đường nội bộ ổ C:. |
| Nói xong không thấy trả lời | (1) app chưa Publish version hoặc chưa bật event im.message.receive_v1; (2) sai CONTROL_CHAT_ID/OWNER_OPEN_ID; (3) bot chưa được thêm vào nhóm. Nhìn cửa sổ bridge xem có log không. |
| Bot báo “❌ Nghe không rõ” với mọi câu | GPU thiếu cuBLAS/cuDNN — Whisper nạp được nhưng suy luận lỗi ngầm. Chạy lại install.ps1, hoặc uv pip install --python .venv\Scripts\python.exe nvidia-cublas-cu12 nvidia-cudnn-cu12. |
| Nghe sai chữ nhiều | WHISPER_MODEL=small nghe tiếng Việt chưa chuẩn. Có GPU thì đổi sang medium trong .env. |
| Trả lời bằng chữ thay vì giọng | edge-tts lỗi mạng tạm, hoặc thiếu ffmpeg → bridge tự rớt về chữ cho khỏi đứt. Kiểm ffmpeg -version, rồi thử lại. |
check-setup.mjs báo thiếu Python / gói | Chưa chạy install.ps1, hoặc PYTHON_BIN trong .env trỏ sai. Chạy lại install.ps1. |
lark-cli báo lỗi auth | Đăng nhập lại lark-cli bằng app của bạn. lark-cli profile list phải có active: true. |
whoami.mjs không in gì khi bạn nhắn | App chưa Publish / chưa bật event / bot chưa vào nhóm — quay lại mục 02. |
Windows không có python | Chỉ có stub Microsoft Store. Dùng uv (install.ps1 ưu tiên uv) và để PYTHON_BIN trỏ vào .venv. |
| TÔM tự nhắn chuyện “chăm sóc khách” | Trong code, CARE_MODE để trống là mặc định BẬT. Muốn tắt phải ghi rõ CARE_MODE=false trong .env. |