Herdr là gì? Quản lý cả team AI Agent trong một cửa sổ

- Published on
- /34 mins read/
Chạy một agent thì cái chậm là model. Chạy năm agent cùng lúc thì cái chậm là… mình.
Chiều thứ Sáu, màn hình của mình trông thế này:
- Tab 1: Claude Code đang refactor module thanh toán.
- Tab 2: Codex đang viết test cho API mới.
- Tab 3: thêm một agent nữa đang lục log production tìm bug.
- Tab 4:
npm run dev. - Tab 5: SSH lên con VPS, có agent đang chạy migration.
Đi pha ly cà phê, quay lại mở tab 2 thì thấy Codex đứng im 20 phút chỉ để hỏi: "Cho chạy rm -rf node_modules không?". Tab 5 thì rớt SSH, agent chết luôn, làm lại từ đầu.
Lỗi không nằm ở agent. Lỗi là cái terminal không hề biết bên trong nó đang có agent. Với nó, Claude Code hay htop cũng chỉ là một process in chữ ra màn hình, vậy thôi.
Herdr làm ra để xử lý đúng chỗ này.
# tóm tắt nhanh
| câu hỏi | trả lời |
|---|---|
| Herdr là gì? | Một terminal multiplexer kiểu tmux, nhưng biết đọc trạng thái AI agent. Viết bằng Rust, chỉ một file binary |
| Có thay Claude Code, Codex không? | Không. Agent nào bạn đang xài thì cứ xài, Herdr chỉ quản lý cái terminal chứa nó |
| Hay nhất ở đâu? | Thanh bên trái hiện trạng thái từng agent: working, blocked, done, idle |
| Tắt cửa sổ, rớt mạng thì sao? | Agent vẫn chạy. Herdr tách server và client, mở lại là thấy y nguyên |
| Agent tự điều khiển được không? | Được. Có CLI và socket API để tạo pane, bật agent khác, giao việc, chờ kết quả |
| Tốn tiền không? | Mã nguồn mở, chạy trên máy bạn, không cần tài khoản, không gửi dữ liệu đi đâu |
Bài viết dựa trên Herdr 0.8.2. Dự án ra bản mới khá dày, nên lệnh nào không chạy thì cứ
herdr --helptrên máy bạn là chuẩn nhất.
# mấy cái khổ khi chạy nhiều agent
Nói Herdr làm gì thì trước hết phải nói mình đang khổ chỗ nào. Mới dùng agent thì sớm muộn cũng gặp, còn dùng lâu rồi chắc đọc tới đây là gật gù.
1. agent đứng chờ mà mình không hay
Agent bây giờ đều có cơ chế xin phép: muốn sửa file, chạy lệnh shell, gọi mạng... là nó dừng lại chờ mình bấm y. Cái này tốt, nên có. Có điều nếu agent nằm ở tab mình không mở, nó cứ ngồi im đó chờ. Thời gian chờ ấy là thời gian chết, không ai làm gì cả.
2. nhảy qua nhảy lại tốn sức hơn mình tưởng
Muốn biết 5 agent đang tới đâu thì phải mở lần lượt 5 tab, đọc màn hình, nhớ lại nó đang làm bước nào. Mỗi lần nhảy tab là một lần đứt mạch. Ai code lâu đều biết, đứt mạch một lần là mất cả buổi mới vào lại được guồng.
3. đóng cửa sổ là mất trắng
Lỡ tay đóng terminal, laptop sập nguồn, Wi-Fi chập chờn làm rớt SSH... process bên trong chết theo. Một agent đã chạy 40 phút, đang nắm cả đống ngữ cảnh mà chết ngang thì mất cả thời gian lẫn tiền token.
4. tmux chỉ gỡ được một nửa
Dân terminal lâu năm sẽ bảo: "Xài tmux đi". Đúng là tmux giữ session rất ổn, chia màn hình cũng ổn. Nhưng tmux không biết pane nào có agent, agent đó đang làm hay đang chờ. Với tmux, pane nào cũng như pane nào.
Khi đã chạy nhiều agent một lúc, câu hỏi không còn là "làm sao cho AI làm giỏi hơn" nữa, mà là "làm sao để mình điều phối cho kịp". Herdr nhắm vào đúng câu hỏi thứ hai.
# vậy Herdr là gì?
README của dự án tự giới thiệu là "the runtime your coding agents live on", tạm hiểu là "chỗ ở" của các coding agent.
Nói cho dễ hình dung thì Herdr là:
- Một terminal multiplexer: chia một cửa sổ terminal thành nhiều workspace, tab, pane, giống tmux hay zellij.
- Biết agent là gì: tự nhận ra các agent CLI quen thuộc chạy trong pane và đọc được chúng đang làm gì.
- Không chết theo cửa sổ: chạy theo kiểu server/client, tắt giao diện thì agent vẫn chạy nền.
- Điều khiển được bằng lệnh: thao tác nào cũng có CLI và socket API, nên agent cũng điều khiển được layout và agent khác.
- Nhẹ: một file binary Rust (giao diện dựng bằng Ratatui), không Electron, chạy bên trong terminal bạn đang dùng (iTerm2, WezTerm, Kitty, Ghostty, Windows Terminal...).
Cũng nên nói rõ Herdr không phải là gì, để khỏi kỳ vọng sai:
| Herdr KHÔNG phải | vì sao |
|---|---|
| một AI agent | Không có model, không gọi LLM. Agent là của bạn, bạn tự mang vào |
| một terminal emulator | Không thay iTerm2 hay WezTerm. Font, theme, phím tắt của terminal giữ nguyên |
| framework multi-agent | Khác LangGraph, CrewAI. Không có graph, không có LLM nào ngầm điều phối |
| dịch vụ cloud | Chạy hoàn toàn trên máy bạn, không cần đăng nhập |
| lớp bọc quanh agent | Không chặn, không sửa input/output của agent, chỉ đứng ngoài nhìn màn hình |
README có một câu tóm gọn khá hay: "herdr doesn't wrap or replace them; it owns their terminals." Tức là Herdr không bọc, không thay agent, nó chỉ giữ cái terminal của agent.
# bên trong Herdr: server, client và cây workspace
server và client
- Server giữ toàn bộ pane và process. Nó chạy nền, bạn có nhìn hay không cũng vậy.
- Client chỉ là cái giao diện gắn vào server. Mở nhiều client cùng lúc cũng được, mỗi cái xem một workspace khác nhau.
- CLI và socket API là cửa thứ ba, để script và agent nói chuyện với server bằng JSON.
Bấm ctrl+b rồi q (detach) thì client thoát, còn server và agent vẫn chạy tiếp. Gõ lại herdr là quay về đúng chỗ cũ.
workspace, tab, pane
| cấp | là gì | nên dùng thế nào |
|---|---|---|
| Workspace | Cấp to nhất, mỗi cái ứng với một dự án (UI gọi là "space") | Mỗi repo, mỗi task hoặc mỗi vụ điều tra một workspace |
| Tab | Một bố cục bên trong workspace | Tách riêng các góc nhìn: agents, logs, server, review |
| Pane | Một terminal thật, chạy một process | Mỗi agent hoặc mỗi lệnh chạy lâu một pane |
Mỗi thứ có một ID riêng, cố định, và đóng rồi thì không bao giờ dùng lại:
workspace : w1
tab : w1:t1
pane : w1:p1
Chi tiết này nhỏ nhưng quan trọng khi viết script: ID phải lấy từ JSON trả về, đừng đoán theo thứ tự trên thanh bên.
ba chế độ phím
Herdr học cách của tmux nhưng tách bạch hơn:
- Terminal mode: gõ gì cũng đi thẳng vào pane đang chọn (lúc bạn đang chat với agent).
- Prefix mode: bấm
ctrl+b, Herdr chờ phím tiếp theo để làm một thao tác. - Navigate mode: chế độ di chuyển giữa workspace và pane bằng phím mũi tên hoặc
h/j/k/l.
Không thích nhớ phím tắt cũng không sao. Herdr hỗ trợ chuột rất tốt: click để chọn pane, kéo viền để đổi kích thước, chuột phải để chia hoặc đóng pane. Người mới hoàn toàn dùng được mà không cần thuộc phím nào.
# phần đáng tiền nhất: Herdr biết agent đang làm gì
Đây là thứ làm Herdr khác tmux. Ai dùng sâu thì nên hiểu kỹ phần này, để biết lúc nào nó đúng, lúc nào nó có thể sai.
năm trạng thái
| trạng thái | nghĩa là | bạn nên làm gì |
|---|---|---|
working | Agent đang làm | Kệ nó |
blocked | Trên màn hình đang có hộp thoại xin phép hoặc câu hỏi | Vào duyệt ngay |
done | Agent làm xong lúc bạn không nhìn, giờ đang rảnh | Vào đọc kết quả |
idle | Agent đang rảnh và bạn đã xem tab của nó rồi | Muốn thì giao việc mới |
unknown | Có agent nhưng Herdr không chắc nó đang ở trạng thái nào | Tự mở ra xem |
done và idle thật ra cùng là "agent đang rảnh". Khác ở chỗ done báo thêm cho bạn biết có kết quả chưa đọc, giống cái chấm "tin nhắn mới" trên Zalo hay Slack. Bạn mở tab đó ra xem là nó chuyển thành idle.
trạng thái được "đẩy" lên cấp trên
Một agent blocked thì pane, tab và cả workspace chứa nó đều hiện là blocked. Một agent working thì workspace sáng lên là đang có việc. Vì vậy chỉ cần liếc thanh bên trái là biết dự án nào đang cần mình, kể cả khi agent đó nằm sâu trong một tab chẳng ai mở.
Cách dùng Herdr gói gọn lại chỉ có vậy: bật vài agent, cho chúng chạy song song, rồi nhìn thanh bên xem chỗ nào cần mình.
Muốn gọn hơn nữa thì đổi danh sách agent từ "xếp theo workspace" sang "xếp theo độ ưu tiên". Lúc đó thanh bên thành một hàng chờ, cái nào cần bạn nhất nằm trên cùng:
[ui]
agent_panel_sort = "priority" # mặc định: "spaces"
status_indicators = "symbols" # mỗi trạng thái một ký hiệu riêng thay vì chấm màuHerdr đoán trạng thái kiểu gì?
Có hai cách. Biết hai cách này thì lúc Herdr báo sai bạn sẽ biết sửa ở đâu.
Cách 1: đọc màn hình (screen manifest). Với các agent phổ biến (Claude Code, Codex, Cursor Agent, Gemini CLI, OpenCode, Copilot CLI, Amp, Grok CLI, Kiro, Cline, Qwen Code, Droid, Pi...), Herdr có sẵn file manifest mô tả "màn hình agent X lúc đang chạy, lúc đang xin phép trông ra sao". Herdr chụp lại phần cuối màn hình rồi so với manifest.
Manifest đi kèm sẵn trong binary và được cập nhật định kỳ từ herdr.dev. Nhờ vậy khi Claude Code đổi giao diện, bạn không nhất thiết phải chờ Herdr ra bản mới. Muốn tự chỉnh thì ghi đè trong ~/.config/herdr/agent-detection/<agent>.toml.
Có một điểm mình thấy họ làm rất có tâm: trạng thái blocked được bắt cực kỳ khắt khe. Herdr chỉ báo blocked khi màn hình khớp đúng với một hộp thoại xin phép hoặc câu hỏi đã biết. Lý do dễ hiểu: báo nhầm vài lần là bạn hết tin thanh bên, lại quay về mở từng tab ra kiểm tra, vậy thì dùng Herdr làm gì nữa.
Cách 2: agent tự báo (integration). Thay vì để Herdr đoán qua màn hình, agent chủ động gọi Herdr báo "tôi đang làm", "tôi đang chờ". Cách này chính xác hơn, lại còn cho Herdr lưu session ID của agent để mở lại đúng cuộc hội thoại cũ khi server khởi động lại.
# cài integration cho agent bạn hay dùng
herdr integration install claude
herdr integration statusKhi Herdr báo sai thì dùng mấy lệnh này để soi:
herdr agent explain <pane-id-hoặc-tên-agent>
herdr server agent-manifests # xem manifest nào đang được dùng
herdr server update-agent-manifests # kéo manifest mới nhất vềNói thêm cho dân kỹ thuật: Đọc màn hình nghe hơi "thủ công", nhưng là lựa chọn rất thực tế. Mỗi agent CLI một kiểu, nhiều cái còn đóng nguồn, điểm chung duy nhất là cái nào cũng vẽ lên terminal. Đọc màn hình giúp Herdr hỗ trợ hơn 20 agent mà không cần bên nào chịu hợp tác. Agent nào muốn chính xác hơn thì đi đường integration.
# cài đặt và làm quen
cài đặt
# macOS / Linux, chọn một trong các cách
brew install herdr
curl -fsSL https://herdr.dev/install.sh | sh
mise use -g herdr
# Windows (PowerShell)
powershell -ExecutionPolicy Bypass -c "irm https://herdr.dev/install.ps1 | iex"
# build từ source (cần cài Rust)
git clone https://github.com/herdrdev/herdr
cd herdr && cargo build --releaseKiểm tra lại:
herdr --version
herdr statuslần chạy đầu
herdrLần đầu mở, Herdr sẽ hỏi bạn muốn nhận thông báo kiểu nào: hiện ngay trong Herdr, nhờ terminal hiện, hay dùng thông báo của hệ điều hành. Chọn xong là vào màn hình chính, chia làm bốn khu:
+----------------+---------------------------------------------+
| SPACES | [agents] [logs] [review] <- tabs |
| | +-------------------+-------------------+ |
| * api | | | | |
| main | | claude | codex | |
| | | (working) | (blocked) | |
| ~ web | | | | |
| feat/login | | +-------------------+ |
| | | | | |
+----------------+ | | npm run dev | |
| AGENTS | | | | |
| ! codex web | +-------------------+-------------------+ |
| ~ claude api | |
+----------------+---------------------------------------------+
| ctrl+b ? help | ctrl+b c new tab | ctrl+b v split |
+--------------------------------------------------------------+- Spaces (góc trên bên trái): danh sách workspace, kèm branch git và trạng thái chung.
- Agents (góc dưới bên trái): tất cả agent đang chạy, gom từ mọi workspace.
- Khu pane (ở giữa và bên phải): terminal thật của bạn.
- Thanh gợi ý (dưới cùng): phím tắt tuỳ theo ngữ cảnh.
bài tập đầu tiên: hai agent chạy song song
- Ở pane đầu tiên,
cdvào repo rồi chạyclaude. - Bấm
ctrl+brồivđể chia đôi màn hình theo chiều dọc. Pane mới chạycodex(hoặc agent nào bạn có). - Giao cho mỗi agent một việc, rồi
ctrl+b cmở tab mới đi làm việc khác. - Để ý thanh bên: agent nào xin quyền là chuyển sang
blocked, có thêm thông báo và tiếng nếu bạn bật. - Bấm
ctrl+b qđể detach, tắt luôn cửa sổ terminal. Mở lại, gõherdr. Mọi thứ vẫn còn, agent vẫn đang chạy.
Phần lớn mọi người "chịu" Herdr từ bước 5.
phím tắt nên nhớ
Tất cả phím dưới đây đều bấm sau prefix ctrl+b:
| phím | làm gì | phím | làm gì |
|---|---|---|---|
? | xem hết phím tắt | q | detach (agent vẫn chạy) |
c | mở tab mới | shift+n | tạo workspace mới |
n / p | tab sau / tab trước | 1..9 | nhảy tới tab số N |
v | chia pane theo chiều dọc | minus | chia pane theo chiều ngang |
h j k l | chuyển sang pane trái/dưới/trên/phải | x | đóng pane |
z | phóng to pane | r | chế độ đổi kích thước |
w | chọn workspace | g | goto |
shift+g | tạo git worktree mới | o | nhảy tới chỗ vừa báo thông báo |
b | ẩn/hiện thanh bên | s | cài đặt |
e | mở scrollback bằng editor | shift+r | nạp lại config |
Ai xài tmux rồi sẽ thấy quen tay. Nếu đang dùng tmux song song và sợ đụng prefix thì đổi phím khác:
[keys]
prefix = "ctrl+space"# chỉnh Herdr theo ý mình
File config nằm ở ~/.config/herdr/config.toml (Windows thì ở %APPDATA%\herdr\config.toml). Cách dễ nhất là xuất file mặc định ra, trong đó đã có sẵn comment giải thích từng dòng:
mkdir -p ~/.config/herdr
herdr --default-config > ~/.config/herdr/config.tomlSửa xong thì nạp lại, không cần tắt agent nào:
herdr server reload-config # hoặc ctrl+b shift+rĐây là bản config mình đang dùng, bạn có thể lấy làm điểm xuất phát:
# ~/.config/herdr/config.toml
[theme]
name = "catppuccin"
auto_switch = true # đổi theo chế độ sáng/tối của terminal
light_name = "catppuccin-latte"
dark_name = "catppuccin"
[terminal]
new_cwd = "follow" # pane mới mở ở cùng thư mục với pane hiện tại
[worktrees]
directory = "~/.herdr/worktrees"
[ui]
agent_panel_sort = "priority" # agent cần mình nhất nằm trên cùng
status_indicators = "symbols" # dễ phân biệt hơn chấm màu, ai yếu màu cũng đọc được
hide_tab_bar_when_single_tab = true
show_agent_labels_on_pane_borders = true
# báo khi agent ở workspace khác đổi trạng thái
[ui.toast]
delivery = "system" # off | herdr | terminal | system
delay_seconds = 1
# chỉnh thông tin hiện trong danh sách agent
[ui.sidebar.agents]
row_gap = 0
rows = [["state_icon", "workspace", "tab"], ["agent"]]
# phím tắt riêng: mở lazygit dạng popup
[[keys.command]]
key = "prefix+alt+g"
type = "popup"
command = "lazygit"
width = "80%"
height = "80%"Vài ghi chú:
delivery = "system"dùng thông báo của hệ điều hành, hợp với ai hay chuyển qua trình duyệt hay Slack. Ngồi suốt trong terminal thì đểherdrcho đỡ ồn.[ui.sound]cho đặt tiếng riêng cho "xong việc" và "cần duyệt", bật tắt theo từng agent. Nghe tiếng là biết nên chạy vào hay cứ để đó, tiện hơn mình tưởng.[[keys.command]]vớitype = "popup"rất tiện: lazygit, btop hay script xem diff, mở đè lên trên mà không làm xáo trộn bố cục.
# làm thật: một feature, ba agent, ba worktree
Phần này cho bạn nào đã quen chạy một agent và muốn tăng lên.
luật bất di bất dịch: hai agent không sửa chung một thư mục
Cho hai agent sửa chung một thư mục là tự rước hoạ: agent A đang chạy test thì agent B sửa file, A thấy test đỏ lại đi "sửa" code của B... Cách xử lý chuẩn là git worktree: mỗi agent một bản checkout riêng, một branch riêng, dùng chung lịch sử .git.
Herdr có sẵn lệnh worktree, mỗi worktree mở ra thành một workspace riêng, thanh bên hiện luôn tên branch và trạng thái git:
herdr worktree create --cwd ~/code/shop --branch feat/payment-retry --base main --label payment
herdr worktree list --cwd ~/code/shopHoặc trên giao diện: ctrl+b shift+g.
cách sắp xếp
script dựng nguyên "phòng làm việc" bằng một lệnh
Sáng nào cũng tạo tay thì mệt, viết script cho nhanh. Lệnh điều khiển nào của Herdr cũng trả về JSON, ghép với jq là vừa đẹp.
Tạo file ~/bin/herdr-feature.sh:
#!/usr/bin/env bash
# dựng workspace + worktree + agent cho một feature
# dùng: herdr-feature.sh <repo-path> <branch> <agent-kind> "<prompt>"
set -euo pipefail
REPO="$1"
BRANCH="$2"
KIND="${3:-claude}"
PROMPT="${4:-}"
NAME="$(echo "$BRANCH" | tr '/' '-' | tr '[:upper:]' '[:lower:]' | cut -c1-32)"
# 1. tạo git worktree, Herdr mở nó thành workspace mới (không giành focus)
WS=$(herdr worktree create --cwd "$REPO" --branch "$BRANCH" --base main \
--label "$NAME" --no-focus | jq -r '.result.workspace.workspace_id')
# 2. lấy pane đầu tiên của workspace vừa tạo
PANE=$(herdr pane list --workspace "$WS" | jq -r '.result.panes[0].pane_id')
# 3. bật agent trong pane đó, lệnh chỉ trả về khi agent sẵn sàng nhận việc
herdr agent start "$NAME" --kind "$KIND" --pane "$PANE"
# 4. giao việc rồi để agent tự chạy, không đứng chờ
if [ -n "$PROMPT" ]; then
herdr agent prompt "$NAME" "$PROMPT"
fi
echo "✅ $NAME đang chạy trong workspace $WS (pane $PANE)"Chạy thử:
chmod +x ~/bin/herdr-feature.sh
herdr-feature.sh ~/code/shop feat/payment-retry claude \
"Thêm cơ chế retry với exponential backoff và idempotency key cho PaymentService. Viết unit test. Không sửa file ngoài module payment."
herdr-feature.sh ~/code/shop feat/payment-tests codex \
"Đọc docs/specs/payment-retry.md và viết integration test cho các kịch bản timeout, duplicate request, partial failure."Ba chỗ cần để ý trong script:
- ID lấy từ JSON (
.result.workspace.workspace_id,.result.panes[0].pane_id), không đoán kiểuw2:p1. ID trong Herdr không theo quy luật nào để mình tự suy ra, đừng bao giờ ghi cứng. agent startchờ agent sẵn sàng rồi mới trả về (mặc định chờ tối đa 30 giây). Nếu agent bị chặn ngay lúc mở (kiểu hỏi "có tin thư mục này không?"), lệnh báo lỗiagent_not_readyđể bạn xử lý, chứ không gửi prompt vào chỗ không ai nghe.- Tên agent (
$NAME) phải khớp regex[a-z][a-z0-9_-]{0,31}và không được trùng. Đặt tên xong thì lệnh nào cũng gọi bằng tên được, dễ đọc hơn pane ID nhiều.
# cho agent điều khiển agent
Phần này dân AI chắc sẽ thích nhất. Vì Herdr có CLI đầy đủ, một agent chạy trong Herdr có thể tự mở pane, bật agent khác, giao việc, chờ rồi đọc kết quả.
biến môi trường Herdr gắn vào mỗi pane
HERDR_ENV=1 # đang chạy trong Herdr
HERDR_WORKSPACE_ID=w1
HERDR_TAB_ID=w1:t1
HERDR_PANE_ID=w1:p1 # pane của chính process này
HERDR_BIN_PATH=... # đường dẫn tới binary herdr
HERDR_SOCKET_PATH=... # socket APINhờ mấy biến này, agent biết mình đang đứng ở đâu và thao tác quanh vị trí của mình (--current), không lỡ tay đụng vào pane bạn đang dùng.
skill có sẵn cho agent
Herdr có sẵn một file "skill" dạy agent cách dùng CLI cho an toàn:
mkdir -p ~/.claude/skills/herdr
herdr --skill > ~/.claude/skills/herdr/SKILL.mdVới Claude Code (hoặc agent nào đọc được skill kiểu này), cài xong chỉ cần nói "dùng Herdr để..." là agent biết làm. Trong skill có vài luật an toàn mình thấy đáng học:
- Kiểm tra
HERDR_ENV=1trước đã, không điều khiển Herdr từ bên ngoài. - Việc chạy nền thì dùng
--no-focus, không giành màn hình của người dùng. - Không đóng workspace, tab, pane nào mà agent không tự tạo.
- Gặp agent đang
blockedthì đọc màn hình rồi hỏi người dùng, không tự bấm "yes".
cách 1: chạy test ở pane bên cạnh rồi đọc kết quả
# mở pane bên phải, cùng thư mục, không giành focus
NEW=$(herdr pane split --current --direction right --cwd "$PWD" --no-focus \
| jq -r '.result.pane.pane_id')
herdr pane run "$NEW" "./gradlew test"
herdr pane wait-output "$NEW" --regex "BUILD (SUCCESSFUL|FAILED)" --timeout 600000
herdr pane read "$NEW" --source recent-unwrapped --lines 150So với để agent tự chạy test trong pane của nó, cách này có hai cái lợi: bạn thấy test chạy ngay bên cạnh, và đống output dài không nhét vào ngữ cảnh của agent cho tới lúc nó cần đọc.
--source có bốn lựa chọn:
| source | đọc phần nào |
|---|---|
visible | đúng phần đang hiện trên màn hình |
recent | output gần đây, giữ nguyên chỗ xuống dòng do tràn |
recent-unwrapped | output gần đây, nối lại các dòng bị tràn, đọc log là hợp nhất |
detection | phần cuối màn hình mà Herdr dùng để đoán trạng thái |
cách 2: một đứa viết, một đứa review
Một agent viết code, một agent khác model review. Dùng hai model khác nhau để đỡ dính chung "điểm mù": model nào cũng khó tự thấy loại lỗi mà chính nó hay mắc.
#!/usr/bin/env bash
# review-loop.sh, chạy trong một pane của Herdr
set -euo pipefail
test "${HERDR_ENV:-}" = 1 || { echo "không chạy trong Herdr"; exit 1; }
# pane cho reviewer
RP=$(herdr pane split --current --direction down --cwd "$PWD" --no-focus \
| jq -r '.result.pane.pane_id')
herdr agent start reviewer --kind codex --pane "$RP"
# writer: giả sử đã có agent tên "writer" đang chạy
herdr agent prompt writer \
"Implement TODO trong src/payment/RetryPolicy.java. Khi xong, commit với message rõ ràng." \
--wait --timeout 1800000
# xem writer dừng ở trạng thái nào
STATE=$(herdr agent get writer | jq -r '.result.agent.agent_status // empty')
if [ "$STATE" = "blocked" ]; then
herdr notification show "writer cần duyệt" --sound request
exit 0
fi
# reviewer đọc commit cuối và báo cáo
herdr agent prompt reviewer \
"Review commit HEAD. Chỉ báo các lỗi thực sự có thể gây bug hoặc lỗ hổng bảo mật, kèm file:line. Ghi kết quả vào /tmp/review.md." \
--wait --timeout 900000
herdr notification show "Review xong" --body "Xem /tmp/review.md" --sound doneVài điều nên biết về agent prompt:
- Agent đang
blockedthì lệnh không gửi mà trả vềagent_blocked. Nhờ vậy prompt của bạn không bị gõ nhầm vào hộp thoại xin phép (rồi vô tình thành câu trả lời "yes"). --waitchờ tới khi agent dừng lại ở một trạng thái:idle,donehoặcblocked.- Sau 5 giây mà agent không nhúc nhích, lệnh trả về
agent_prompt_stalledthay vì treo mãi.
cách 3: hỏi một câu, ba agent cùng trả lời
Gặp bug khó thì hỏi cùng một câu cho ba agent khác nhau rồi so đáp án, giống đi khám mà hỏi thêm ý kiến bác sĩ khác:
#!/usr/bin/env bash
set -euo pipefail
Q="Đọc logs/incident-1003.log và src/order/. Tìm nguyên nhân gốc của lỗi duplicate order. Trả lời ngắn gọn, có dẫn chứng file:line."
for KIND in claude codex gemini; do
P=$(herdr pane split --current --direction right --cwd "$PWD" --no-focus \
| jq -r '.result.pane.pane_id')
herdr agent start "inv-$KIND" --kind "$KIND" --pane "$P"
herdr agent prompt "inv-$KIND" "$Q"
done
# chờ cả ba
for KIND in claude codex gemini; do
herdr agent wait "inv-$KIND" --timeout 1200000 || true
done
herdr notification show "3 agent đã điều tra xong" --sound doneBa đứa cùng chỉ một chỗ thì khá chắc. Mỗi đứa nói một kiểu thì đó chính là chỗ bạn nên tự đào sâu.
socket API cho ai muốn tích hợp sâu
CLI thật ra chỉ là lớp mỏng bọc ngoài socket API dạng JSON. Muốn làm dashboard, bot Slack hay nối vào hệ thống riêng thì nói chuyện thẳng với socket ở $HERDR_SOCKET_PATH:
{
"id": "req_1",
"method": "pane.split",
"params": { "pane_id": "w1:p1", "direction": "right", "ratio": 0.333 }
}Đăng ký nhận sự kiện mỗi khi agent đổi trạng thái, có cái này là tự làm được hệ thống cảnh báo riêng:
{
"id": "sub_1",
"method": "events.subscribe",
"params": {
"subscriptions": [{ "type": "pane.agent_status_changed", "pane_id": "w1:p1" }]
}
}Xem toàn bộ schema:
herdr api schema --json # mọi method, request, response, event
herdr api snapshot # trạng thái hiện tại của cả sessiontự viết agent thì báo trạng thái cho Herdr
Nếu bạn đang tự làm agent (bằng Claude Agent SDK, LangGraph, hay chỉ một vòng lặp Python), thêm vài lệnh là nó hiện lên Herdr đẹp như agent xịn:
# lúc bắt đầu làm
"$HERDR_BIN_PATH" pane report-agent "$HERDR_PANE_ID" \
--source my-agent --agent my-agent --state working --seq 1
# lúc chờ người dùng duyệt
"$HERDR_BIN_PATH" pane report-agent "$HERDR_PANE_ID" \
--source my-agent --agent my-agent --state blocked --seq 2
# lúc thoát
"$HERDR_BIN_PATH" pane release-agent "$HERDR_PANE_ID" \
--source my-agent --agent my-agent --seq 3--seq phải tăng dần để Herdr bỏ qua những báo cáo tới trễ, sai thứ tự. Đây là chiêu quen thuộc trong hệ thống phân tán, giống sequence number của TCP hay cột version trong optimistic locking. Nhớ kiểm tra HERDR_ENV=1 trước, để agent của bạn vẫn chạy bình thường khi không nằm trong Herdr.
# agent chạy trên server, mình ngồi laptop xem
Trường hợp rất hay gặp: cho agent chạy trên VPS hoặc máy build mạnh (gần database staging, không hao pin laptop, chạy xuyên đêm được).
herdr --remote user@build-box
herdr --remote user@build-box --session agentsVới --remote, server Herdr chạy trên máy từ xa, còn client chạy trên laptop của bạn. Rớt mạng thì agent trên server vẫn chạy, nối lại là thấy ngay. Phím tắt và config là của máy bạn (--remote-keybindings local là mặc định), nên cảm giác y như làm trên máy mình.
Herdr còn cho gom nhiều máy vào một cửa sổ: workspace trên máy mình và workspace trên các máy SSH đã lưu nằm chung một thanh bên, danh sách agent gộp lại, máy nào rớt thì máy đó tự nối lại, không ảnh hưởng máy khác. Phần đăng nhập vẫn do OpenSSH lo, Herdr không lưu mật khẩu hay private key. Key có passphrase thì nhớ ssh-add trước.
# cái gì còn, cái gì mất?
Chỗ này nhiều người hiểu nhầm nên nói cho rõ:
| chuyện gì xảy ra | process agent | bố cục (workspace/tab/pane/thư mục) | cuộc hội thoại của agent |
|---|---|---|---|
| detach, tắt cửa sổ terminal | ✅ vẫn chạy | ✅ y nguyên | ✅ y nguyên, vì process chưa hề dừng |
rớt SSH (khi dùng --remote) | ✅ vẫn chạy | ✅ y nguyên | ✅ y nguyên |
| khởi động lại Herdr server | ❌ dừng | ✅ được khôi phục | ⚠️ chỉ khi agent có integration hỗ trợ |
| khởi động lại máy | ❌ dừng | ✅ khôi phục từ bản lưu | ⚠️ như trên |
Thêm vài cơ chế:
- Lưu bố cục: Herdr giữ tối đa 48 bản lưu bố cục để bạn khôi phục bằng tay.
- Mở lại đúng cuộc hội thoại: agent có integration sẽ báo session ID cho Herdr, nên sau khi server khởi động lại, Herdr mở agent lên đúng cuộc hội thoại cũ (ví dụ dùng
--resumecủa agent). - Phát lại nội dung pane: phải tự bật, chỉ chạy khi bố cục khớp chính xác bản lưu.
- Chuyển giao khi cập nhật (đang thử nghiệm):
herdr update --handoffcố gắng chuyển các pane đang chạy sang server mới khi cập nhật Herdr, để process khỏi phải dừng.
Rút ra: detach thoải mái, nhưng đừng khởi động lại server khi agent đang làm dở. Và cài integration cho mấy agent chính để có đường lui.
# so với các lựa chọn khác
| tiêu chí | Herdr | tmux / zellij | terminal "AI-native" (Warp...) | mở nhiều tab thường |
|---|---|---|---|---|
| biết trạng thái agent | ✅ thanh bên + thông báo | ❌ | một phần, thường chỉ agent nhà làm | ❌ |
| giữ session khi tắt | ✅ | ✅ | tuỳ sản phẩm | ❌ |
| dùng agent CLI nào cũng được | ✅ hơn 20 agent | ✅ (nhưng không biết gì về agent) | thường ưu tiên agent tích hợp sẵn | ✅ |
| giữ terminal đang dùng | ✅ chạy bên trong | ✅ | ❌ phải đổi terminal | ✅ |
| có API cho agent điều khiển | ✅ CLI + socket, có skill | ⚠️ tự chế bằng tmux send-keys | tuỳ sản phẩm | ❌ |
| dùng chuột | ✅ rất tốt | ⚠️ phải cấu hình | ✅ | ✅ |
| độ chín | ⚠️ còn mới (0.x) | ✅ rất chín | tuỳ sản phẩm | — |
So với subagent hay agent team có sẵn trong agent (ví dụ subagent của Claude Code): hai thứ này nằm ở hai tầng khác nhau, dùng chung được chứ không loại nhau.
- Subagent trong một agent: do model tự chia việc, chạy ngầm, hợp để chẻ nhỏ một task.
- Herdr: do người (hoặc script) điều phối, agent nào cũng là một terminal bạn nhìn thấy và nhảy vào được, trộn nhiều hãng model cũng được.
Ví von cho dễ nhớ: subagent giống mấy bạn trong nhóm tự chia việc với nhau, còn Herdr là cái văn phòng mở, ngồi một chỗ là thấy cả team.
# khi nào không cần Herdr
Nói ưu điểm rồi thì cũng phải nói thẳng mấy chỗ chưa ổn:
- Bạn chỉ chạy một agent. Một cửa sổ terminal là đủ rồi. Herdr chỉ đáng khi chạy từ hai agent trở lên, hoặc khi cần giữ session qua SSH.
- Bạn cần thứ gì thật ổn định. Herdr mới ở bản 0.x, ra bản liên tục, API và phím tắt còn có thể đổi. Theo mấy bài review, dự án chủ yếu do một người phát triển chính. Định đưa vào quy trình bắt buộc cho cả công ty thì nên cân nhắc.
- Agent của bạn không nằm trong danh sách hỗ trợ và cũng không tự báo trạng thái. Herdr vẫn chạy nó như một terminal bình thường, nhưng bạn mất cái hay nhất là thanh trạng thái.
- Đọc màn hình thì có lúc trật, nhất là khi agent vừa đổi giao diện. Manifest cập nhật từ xa đỡ được phần lớn, nhưng thỉnh thoảng bạn vẫn sẽ thấy
unknown. - Herdr không giúp bạn đỡ tốn tiền. Năm agent chạy song song là đốt token gấp năm. Herdr giúp điều phối, không giúp tiết kiệm.
# kinh nghiệm khi "quản lý" một team agent
Có công cụ rồi thì cách mình làm việc mới là thứ quyết định. Mấy điều dưới đây mình rút ra sau một thời gian dùng, đa số áp dụng được cả khi không dùng Herdr.
1. bắt đầu với 2 đến 3 agent thôi
Giống Kanban giới hạn số việc đang làm: số agent hợp lý không phải số nhiều nhất máy chạy nổi, mà là số nhiều nhất mình review kịp. Năm agent đẻ ra năm cái diff, đọc không xuể thì chỉ là đang sản xuất nợ kỹ thuật nhanh hơn thôi.
2. xử lý theo thứ tự blocked, rồi done, rồi tới phần còn lại
blocked là thời gian chết, xử lý trước. done là kết quả đang chờ, xử lý sau. Bật agent_panel_sort = "priority" là thanh bên tự xếp đúng thứ tự này.
3. một agent, một worktree, một branch
Với task có sửa code thì không có ngoại lệ. Agent chỉ đọc (review, đọc log) thì dùng chung repo chính cũng được.
4. đặt tên agent cho dễ hiểu
payment-retry, reviewer, inv-claude dễ nhìn hơn nhiều so với claude, claude, claude. Mà tên cũng là thứ script dùng để gọi agent.
5. giao việc phải có giới hạn rõ ràng
Prompt cho agent chạy nền nên có đủ: làm gì, được sửa chỗ nào ("không sửa file ngoài module payment"), xong là khi nào ("test pass thì commit"). Agent càng chạy lâu không ai trông thì giới hạn càng phải rõ.
6. có Herdr rồi cũng đừng tắt chế độ xin phép
Herdr giúp mình duyệt nhanh hơn, vậy thì càng nên giữ bước duyệt chứ không phải bỏ nó đi. Muốn agent tự chủ hơn thì dùng danh sách cho phép cụ thể (cho chạy test, cấm rm, cấm git push) thay vì bật "cho phép hết".
7. quyền điều khiển Herdr là quyền rất lớn
Agent nào gọi được herdr pane run hay herdr agent send-keys là agent đó chạy được lệnh ở mọi pane, và bấm duyệt thay cho agent khác được luôn. Đây là lỗ hổng có thật, nhất là khi agent đọc nội dung không đáng tin (issue GitHub, trang web, log) mà bên trong có thể cài prompt injection. Chỉ cài Herdr skill cho agent khi thật sự cần điều phối, và luôn giữ nguyên tắc "gặp blocked thì hỏi người".
8. cuối ngày nhớ dọn dẹp
herdr agent list # còn agent nào đang chạy?
herdr worktree list --cwd ~/code/shop # worktree nào merge rồi?
herdr worktree remove --workspace <id> # xoá worktree đã xongNgày nào cũng tạo vài cái thì worktree với workspace bỏ quên chất đống nhanh lắm.
# checklist bắt đầu
ngày 1: làm quen
- cài Herdr, chạy
herdr, chọn kiểu thông báo - chạy 2 agent ở 2 pane, xem thanh bên đổi trạng thái khi agent xin quyền
- thử detach (
ctrl+b q), tắt terminal, mở lại bằngherdr - xem hết phím tắt bằng
ctrl+b ?
tuần 1: cấu hình
-
herdr --default-config > ~/.config/herdr/config.toml - bật
agent_panel_sort = "priority"và thông báo hệ thống -
herdr integration install <agent>cho mấy agent dùng chính - tạo worktree đầu tiên bằng
ctrl+b shift+g
tuần 2: tự động hoá
- viết script dựng workspace + worktree + agent cho một feature
- thử kiểu một đứa viết, một đứa review với hai model khác nhau
- có VPS thì thử
herdr --remotecho mấy task chạy qua đêm
hàng tuần
- agent nào hay
blockedvì cùng một lệnh → cân nhắc thêm lệnh đó vào danh sách cho phép - số agent có vượt sức review của mình không? → giảm bớt
- dọn worktree và workspace đã xong
# tổng kết
| cái khổ khi chạy nhiều agent | Herdr xử lý bằng |
|---|---|
| không biết agent nào đang chờ duyệt | trạng thái blocked nổi lên thanh bên, kèm thông báo |
| không biết agent nào đã xong | trạng thái done, kiểu "tin nhắn chưa đọc" |
| mở 5 tab để xem 5 agent | một thanh bên, gom agent từ mọi workspace |
| lỡ tắt terminal, rớt SSH | server/client, detach, --remote |
| agent sửa đè code của nhau | herdr worktree, mỗi agent một worktree, một workspace |
| điều phối tay lặp đi lặp lại | CLI, socket API và agent skill để viết script |
Herdr không làm agent của bạn thông minh hơn. Nó làm một việc nhỏ hơn nhưng giai đoạn này lại rất cần: giúp mình không trở thành cái cổ chai khi làm cùng nhiều agent.
Agent ngày càng giống đồng nghiệp ngồi làm song song với mình. Kỹ năng quan trọng của dev vì thế cũng dần chuyển từ "code nhanh" sang "giao việc rõ, review nhanh, điều phối khéo". Có một công cụ nhìn được cả team là bước đầu cho chuyện đó.
Cứ bắt đầu với hai agent. Nhìn thanh bên. Gặp blocked thì xử lý trước. Quen tay rồi hẵng tăng lên.
Tài liệu tham khảo:
- GitHub: herdrdev/herdr
- Tài liệu chính thức: herdr.dev/docs
- Agents và cách Herdr nhận diện trạng thái
- Socket API
- Session state và persistence
Chỉ là những ghi chép cá nhân với hy vọng mang lại chút giá trị. Nếu thấy hữu ích, đừng ngại chia sẻ cho bạn bè & đồng nghiệp nhé!
Happy coding 😎 👍🏻 🚀 🔥.
On this page
- # tóm tắt nhanh
- # mấy cái khổ khi chạy nhiều agent
- 1. agent đứng chờ mà mình không hay
- 2. nhảy qua nhảy lại tốn sức hơn mình tưởng
- 3. đóng cửa sổ là mất trắng
- 4. tmux chỉ gỡ được một nửa
- # vậy Herdr là gì?
- # bên trong Herdr: server, client và cây workspace
- server và client
- workspace, tab, pane
- ba chế độ phím
- # phần đáng tiền nhất: Herdr biết agent đang làm gì
- năm trạng thái
- trạng thái được "đẩy" lên cấp trên
- Herdr đoán trạng thái kiểu gì?
- # cài đặt và làm quen
- cài đặt
- lần chạy đầu
- bài tập đầu tiên: hai agent chạy song song
- phím tắt nên nhớ
- # chỉnh Herdr theo ý mình
- # làm thật: một feature, ba agent, ba worktree
- luật bất di bất dịch: hai agent không sửa chung một thư mục
- cách sắp xếp
- script dựng nguyên "phòng làm việc" bằng một lệnh
- # cho agent điều khiển agent
- biến môi trường Herdr gắn vào mỗi pane
- skill có sẵn cho agent
- cách 1: chạy test ở pane bên cạnh rồi đọc kết quả
- cách 2: một đứa viết, một đứa review
- cách 3: hỏi một câu, ba agent cùng trả lời
- socket API cho ai muốn tích hợp sâu
- tự viết agent thì báo trạng thái cho Herdr
- # agent chạy trên server, mình ngồi laptop xem
- # cái gì còn, cái gì mất?
- # so với các lựa chọn khác
- # khi nào không cần Herdr
- # kinh nghiệm khi "quản lý" một team agent
- 1. bắt đầu với 2 đến 3 agent thôi
- 2. xử lý theo thứ tự blocked, rồi done, rồi tới phần còn lại
- 3. một agent, một worktree, một branch
- 4. đặt tên agent cho dễ hiểu
- 5. giao việc phải có giới hạn rõ ràng
- 6. có Herdr rồi cũng đừng tắt chế độ xin phép
- 7. quyền điều khiển Herdr là quyền rất lớn
- 8. cuối ngày nhớ dọn dẹp
- # checklist bắt đầu
- # tổng kết