@lean4/agents-group
v1.7.18
Published
Web terminal panel where multiple AI agents (CodeBuddy / Claude / Codex / shell) act as group members in a single chat — #mention to dispatch, cross-agent forwarding, JSONL persistence, 5x5 LCD activity indicators.
Downloads
358
Maintainers
Readme
@lean4/agents-group
A Web terminal panel where multiple AI agents act as group members in a single chat. Built on WebSocket + PTY, runs a singleton local web service, and lets you orchestrate CodeBuddy / Claude / Codex / shell terminals through #mention dispatch, agent‑to‑agent forwarding, persistent JSONL transcripts, and a miniterm‑style 5×5 LCD activity indicator per member.
Install once, run anywhere, and your local terminals become a chat group.
Highlights
- Three views, switchable from the sidebar:
- Terminal — classic single‑terminal
- Cards (
agents-view) — a grid of every terminal - Group (
agents-group) — chat panel with message stream + member list (default landing view)
- Supported terminal tools (any mix in one group):
- CodeBuddy (
codebuddy) — default AI CLI - Claude Internal (
claude-internal) - Codex Internal (
codex-internal) —codex-internal resume <id>for resuming sessions - Shell — login shell (
$SHELL -i, PowerShell on Windows). No AI; great forls/build commands inside the same group.
- CodeBuddy (
#mentionto dispatch. Click a member in the chat, the input box auto‑prefixes#name. Plain send (no prefix) becomes an owner note.Enterto send,Shift+Enterfor newline. Picked#instead of@to avoid clashing with CodeBuddy's built‑in@file/@./pathreference syntax.- Cross‑agent forwarding. When an agent's reply contains
#otherAgent, the message is automatically forwarded — gated by a per‑agent whitelist with a 3‑hop depth cap to prevent loops. - Live
cbc-replystreaming. The server watches each CodeBuddy session JSONL (~/.codebuddy/projects/<key>/<sessionId>.jsonl) viafs.watch+ a 1s poll fallback. Reasoning, function‑calls, and final assistant messages all appear in the chat in real time — even when you typed directly into the terminal, not via the group panel. - 5×5 LCD activity per member (7 states, ported from a miniterm‑style indicator): Active (comet), Connecting, Done (✓ flash), Idle (gentle breath), Quiet, Confirm (?), Error (×), Offline.
- Per‑agent context window. Each agent has its own context size (default 5 recent group messages;
0for none; shell is always0). The context is wrapped as a clearly‑labeled Markdown block, separated from the user's current input by a strong## 我的输入heading, so the model never confuses history with the current question. - Append‑only transcript. Everything is persisted to
~/.cbc-web/group-chat.jsonl(note,at,cbc-reply,cbc-stream,agent-cross,system,shell-out,default-reply). Filter chips + search box at the top of the chat. - Token‑gated HTTP. Single random access token, written into a cookie on first visit so the URL bar stays clean afterward.
- Singleton CLI with
start / stop / restart / status / config / url / tokensubcommands. Configurable default port and default terminal tool — seeconfigbelow.
Install
Requires Node.js >= 12. node-pty is an optional dependency: when it builds successfully you get a full PTY; otherwise the package still installs and falls back to a script‑based PTY on Linux/macOS, or a shell pipe on Windows.
npm install -g @lean4/agents-groupAfter install the package provides two equivalent global commands: agents-group and cbc-web (they're aliases for the same binary).
Windows note: if node-pty fails to build, the terminal falls back to a PowerShell pipe with reduced ANSI/interactive fidelity. Installing the build toolchain first (windows-build-tools, Visual Studio Build Tools) usually fixes it.
Quick start
agents-group # equivalent: cbc-web startThe CLI is a global singleton — running it again won't spawn a second instance; it prints the access URLs of the running one.
Sample output:
agents-group started: pid=12345 port=9234
localhost: http://localhost:9234/?token=<token>
local-ip: http://<your-ip>:9234/?token=<token>Open the URL once and the server writes the token into an HttpOnly cookie, then redirects to a clean URL.
Commands
agents-group # start the singleton and print URLs
agents-group start # same
agents-group status # show running state: pid, port, sessions, terminals
agents-group token # print the persistent access token
agents-group url # print localhost + LAN URLs with the token baked in
agents-group stop # stop the singleton
agents-group restart # stop then start
agents-group config # show current configuration
agents-group config port [num] # set HTTP port (interactive when no arg)
agents-group config tool [name] # set default terminal tool (codebuddy/claude-internal/codex-internal/shell)
agents-group helpAll cbc-web ... invocations are accepted as aliases.
The Group Chat panel
┌──────────────────────────────────────┬────────────────┐
│ Message stream (Markdown rendering) │ Members │
│ ┌──┐ │ ● cbc-main │
│ │主│ #buglist take a look at ... │ ● cbc-pr │
│ └──┘ │ ○ claude-1 │
│ ┌──┐ │ ✓ codex-1 │
│ │CB│ Got it, looking now ... │ — sh-build │
│ └──┘ │ │
├──────────────────────────────────────┤ │
│ Target: #buglist ctx: 5 │ │
│ [input .......................][Send] │
└──────────────────────────────────────┴────────────────┘Send semantics
#name <text>→ dispatched to that agent's PTY (bracketed paste +\r); for shell members the message is sent raw +\nwith no context wrapper, so it's friendly for ad‑hoc commands.<text>without prefix → an owner note persisted into the transcript but not sent to any agent.Entersends;Shift+Enterinserts a newline. IME composition is respected.
Right‑rail member interactions
- Click row → toggle this member as
#mentiontarget. - Right‑click or hover ⓘ → open a profile card (name, cwd, tool, status, config summary).
- Hover ⚙ → open the agent configuration modal.
5×5 LCD status legend
| State | Visual | Trigger | | --- | --- | --- | | Active | Outer ring green comet, 1.6 s period | Meaningful PTY output (heartbeat redraws are filtered) | | Connecting | Same comet, 0.9 s period | CBC streaming intermediate state | | Done | 5×5 ✓ glyph, flashes 1.6 s | active → idle edge — a reply just finished | | Idle | Subtle breath (0.7 ~ 1.0) | Online, no work | | Quiet | Dim steady green | 30 s without any activity | | Confirm | 5×5 ? glyph, blinking | Awaiting confirmation (reserved) | | Error | 5×5 × glyph | Abnormal exit | | Offline | Grey, static | PTY closed |
Per‑agent configuration
Persisted at ~/.cbc-web/agent-config.json, indexed by terminalId:
- Context size — how many recent group messages to wrap as Markdown context when dispatching. Default
5;0means "ignore the group".shelltool is locked at0. - Whitelist — toggle which other members this agent is allowed to forward to via
#otherName. Defaults to all‑open.
Cross‑agent forwarding
When an agent's final reply contains #someoneElse:
- if the target is in this agent's whitelist, it's automatically forwarded as an
agent-crossmessage; - a
systemnote appears in the chat (↳ detected #target in cbc-main's reply, forwarded (depth 1)); - loops are prevented by a depth cap of 3 hops; the counter resets after 5 s of inactivity.
Transcript
Every message lands in ~/.cbc-web/group-chat.jsonl (append‑only). Each record carries id / ts / from / fromTool / to / toName / kind / text / terminalId / sessionId. Kinds:
note— owner note (no agent)at— owner → agent#mentioncbc-reply— final assistant reply from a CodeBuddy sessioncbc-stream— reasoning / tool‑call interim (rendered live, not persisted into the context window)agent-cross— cross‑agent forwarddefault-reply— non‑CBC tool's stock replyshell-out— shell tool outputsystem— system notices
Toolbar filters: All / Owner notes / CBC replies / Cross‑agent + a debounced full‑text search box.
Rename safety
Double‑click a terminal tab to rename. The chat panel keeps everything in sync:
- members list re‑renders to the new name;
- if the renamed member is currently selected, the input prefix, send button label, and hint pill all update;
- the
cbc-replywatcher is re‑bound to the new name; - existing transcript entries keep the old name (so past dialogue is preserved verbatim).
Token model
- Generated randomly on first run.
- Stable: stays the same across restarts unless you remove
~/.cbc-web/token. - Required by both HTTP requests and Socket.IO connections.
- Use
agents-group urlfor a copy‑paste ready URL with the token.
State directory
Default ~/.cbc-web/:
token # the persistent access token
runtime.json # service / browser connections / sessions snapshot
sessions.json # managed CodeBuddy session PIDs (for restart restore)
config.json # CLI configuration (port, defaultTool)
group-chat.jsonl # append‑only group transcript
agent-config.json # per‑agent ctx + whitelist
cbc-web.log # backend logOverride with CBC_WEB_STATE_DIR=/some/path agents-group start.
Default workspace and auto‑task directories
Linux / macOS: /data/workspace/cbc-web/ (falls back to $HOME on macOS)
Windows: %USERPROFILE%/cbc-web-workspace/When you create a new session/terminal without specifying cwd, the server creates today's incremental task directory under the workspace root:
<workspace-root>/20260612-task_1
<workspace-root>/20260612-task_2Override with CBC_WEB_WORKSPACE_ROOT=/your/path.
Status
agents-group statusShows pid, port, started‑at, browser connections, every session and its terminals (pid, cwd, alive). The same info is available at /api/status after auth.
Environment variables
| Variable | Default | Purpose |
| --- | --- | --- |
| CBC_WEB_STATE_DIR | ~/.cbc-web | State directory |
| CBC_WEB_WORKSPACE_ROOT | platform default | Auto‑task directory root |
| CBC_WEB_DEFAULT_TOOL | codebuddy | Default terminal tool (set by config tool) |
| PORT / CBC_WEB_PORT | 9234 | HTTP port |
| DISCONNECT_TIMEOUT_MS | 300000 | How long a session is kept after the last browser disconnects |
| CBC_WEB_CROSS_MAX_DEPTH | 3 | Max hops in agent‑to‑agent forwarding chain |
| CBC_WEB_CBC_WATCH_TIMEOUT_MS | 24 h | Idle timeout for the per‑terminal CBC watcher |
Stack
- Node.js + Express
- Socket.IO (single namespace; one room per persistent session)
- PTY: prefers
node-pty, falls back to systemscript(POSIX) or a PowerShell pipe (Windows) - xterm.js + Vite‑built front end
License
MIT
