Phiếu lệnh triển khai · TÔM Voice · app chạy tại máy

Nói vào nhóm Lark,
Claude Code làm trên máy bạn

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.

  1. Bạn nói / gõtrong nhóm điều khiển
  2. lark-clilong connection, không cần URL
  3. Whispernghe ra chữ, chạy tại máy
  4. Claude Codelàm việc trong BRAIN_ROOT
  5. edge-ttsđọc trả lời bằng giọng
hoangminhhoagpt-dot/mentor-club-ai-assistant
01

TÔM chạy ở đâu, ai ra lệnh được

Đọc kỹ chỗ này trước

Máy của bạn máy chủ. Không fork, không Secrets, không workflow.

Đâ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ỏiTrả lời
Chạy ở đâuMá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ì saoTÔ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ề đâuGắn thẳng vào tin của bạn — nói thì nghe giọng, gõ thì đọc chữ
Ai ra lệnh đượcChỉ bạn, và chỉ trong nhóm điều khiển — người khác nhắn vào, TÔM lờ đi
Quyền hạn — cân nhắc thật

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.

02

Việc tay thứ nhất — app Lark & nhóm điều khiển

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.

  1. Tạo app + bật Bot

    open.larksuite.com (bản .cn: open.feishu.cn) → Developer ConsoleCreate Custom AppAdd features → Bot.

  2. Bật đủ 3 scope ở Permissions & Scopes

    • im:message — nhận tin
    • im:message:send_as_bot — gửi tin thay bot
    • im:resourcetả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.
  3. Bật event ở Events & Callbacks

    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.

  4. PUBLISH version — bẫy số một

    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.

  5. Lấy App ID + App Secret

    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.

  6. Tạo nhóm điều khiển + thêm Bot vào nhóm

    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.

  7. Đăng nhập lark-cli bằng chính app này

    Cà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
Ba cái bẫy đã dính thật: (1) quên Publish version → event/scope không hiệu lực; (2) thiếu 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.
03

Công cụ nền — 5 thứ, cài một lần

Cần cóKiểm bằngChưa có thì cài
Node.js ≥ 18node -vTải bản LTS ở nodejs.org
Python 3.10–3.12uv --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"
ffmpegffmpeg -versionwinget install Gyan.FFmpegmở PowerShell mới rồi kiểm lại
lark-clilark-cli --versionnpm i -g @larksuite/cli
claudeclaude --versionCài Claude Code CLI và đăng nhập trên máy này
Windows không có 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.
Không cần biết máy mình có GPU hay không. Khối lệnh giao cho Claude Code tự chạy 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.
04

Điền một lần, đủ mọi giá trị

Lấy ở Credentials & Basic Info của app Lark. Luôn bắt đầu bằng cli_.
Chỉ dùng để đăng nhập lark-cli, không bao giờ ghi vào repo hay .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.
Thư mục bạn cho Claude toàn quyền thao tác khi nhận lệnh. Để trống = thư mục cha của repo. Chỉ trỏ vào thư mục bạn chấp nhận cho AI sửa.
Giọng edge-tts của Microsoft, miễn phí. Đổi lúc nào cũng được ở dòng VOICE_CODE trong .env.
Bộ não trả lời bạn qua Lark. Đổi sau trong .env không cần cài lại gì.
Chưa tích thì khối lệnh sẽ yêu cầu Claude dẫn bạn làm phần đó theo docs/02-tao-app-lark.md trước khi đi tiếp.
Ba thứ cố tình không hỏi bạn, vì máy tự biết được: OWNER_OPEN_IDCONTROL_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.
Mọi giá trị bạn gõ chỉ nằm trong trình duyệt — trang không gửi đi đâu, không lưu lại. Đóng tab là mất.
05

Khối lệnh — sao chép rồi dán vào Claude Code

Lệnh triển khai TÔM Voice

    

Chưa điền ô nào — khối lệnh đang ở dạng mẫu.

Mở Claude Code ở bất kỳ thư mục nào rồi dán khối này vào là được: mục 0 đã bảo nó tự 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.
Mục 7 cố tình không cho Claude tự bấm nút. 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ì.
06

Đường đi của một câu nói

  1. Bạn bấm micronói vào nhóm điều khiển
  2. lark-cli consumelong connection kéo event về máy, không cần URL công khai
  3. Tải audio + ffmpegđây là chỗ cần im:resource
  4. faster-whisperserver thường trú; GPU lỗi thì tự lùi CPU
  5. claude -pClaude Code headless chạy trong BRAIN_ROOT
  6. edge-tts → opusgắn trả lời vào đúng tin bạn vừa gửi

Tin 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 repoViệc của nó
scripts/lark-voice-bridge.mjsTrá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.pyServer 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.mjsIn ra OWNER_OPEN_ID + CONTROL_CHAT_ID khi bạn nhắn thử
scripts/check-setup.mjsCổng chốt môi trường — 10 dòng phải ✔ hết
scripts/start.ps1Nú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.mjsTuỳ 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.mjsCổng chốt gói — đủ mảnh chưa, chạy ở thư mục gốc repo
07

Cổng chốt — hai lệnh, phải xanh hết

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:

Cổng chốt không kiểm được app đã Publish hay bot đã vào nhóm chưa — hai thứ đó nằm phía Lark. Phép thử thật là chạy whoami.mjs rồi nhắn một tin: im lặng không in gì = một trong hai việc đó chưa xong.
08

Bật TÔM, tạo shortcut, và 24/7

  1. Bật — bằng tay bạn

    powershell -ExecutionPolicy Bypass -File scripts/start.ps1

    Chờ tới khi cửa sổ hiện đủ hai dòng: ✅ Bridge sẵn sàng.✅ 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.

  2. Nói thử một câu

    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.

  3. Shortcut Desktop — nhớ dùng đường ổ C:

    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()
  4. Chạy ngầm 24/7 — tuỳ chọn, và hãy nghĩ kỹ

    Đă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ì.

Test không tốn token: đặt 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.
09

Bẫy thường gặp — đúc kết từ triển khai thật

Hiện tượngNguyên nhân thật & cách sửa
Double-click start.ps1 → cửa sổ tắt phụtFile .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 đượcShortcut 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âuGPU 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ềuWHISPER_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ọngedge-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óiChư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ắnApp 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ó pythonChỉ 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.