🔶 Legbar:在一个终端中并排查看实时 AI Agent 会话与 GitHub CI
英文标题:🔶 Legbar – live AI agent sessions beside GitHub CI, in one terminal
Legbar 将 Claude Code、Cursor Agent 的实时会话状态,与跨仓库的 GitHub Actions 和 Pull Request 状态整合到同一个终端界面中。它通过统一的发现层读取会话、转录记录、Git 状态与 GitHub 数据,避免 Agent 面板和 CI 面板出现信息不一致。工具支持 macOS、Linux 和 Windows,仅依赖 Python 3.9+ 标准库,并可通过 pip、npm、Homebrew、winget 或 apt 安装。对开发者而言,Legbar 尤其解决了多 Agent 同时操作同一工作副本、等待人工输入被遗忘,以及失败 CI 被滚出视野等问题。
260.5 KB
222.3 KB
121.0 KB
中文
用一个屏幕查看整支 Agent 队列:实时 Agent 会话与 GitHub CI 并排呈现,二者来自同一发现层,因此两个面板不会出现不一致。
roost 回答的是:模型正在做什么? leghorn 回答的是:仓库正在做什么? 两者可以同时成立,而且任一视图都不包含另一个——因此,监控一支 Agent 队列过去意味着盯着两个窗口,再靠肉眼将信息关联起来。legbar 将两条信息通道绘制在同一个画布上。
legbar 5 sessions | 1 cursor | 1 need input | 15 ci red | 125k held | 18:37:00
NEEDS YOU GITHUB
!! CONTESTED heron-ops 2 sessions in one working copy: c5468eb1, heron~ X roost ci ! WAITING heron-ops-3c needs your reply -- 12m -- fix contested false~ X roost #56 ci: skip winget~ CI RED roost ci > leghorn release
WAITING ON YOU
!cc-heron-op~ FB5 ###------- 32% you 12m 3 2^1 fix contested false alarm
cc-swamp-op OP5 ##-------- 25% you 12m - ~1 draft discussions packet
WORKING NOW
cc-heron-op~ FB5 #--------- 10% ai 3s 2 clean survey henhouse drift
STARTING
!cu-c5468eb1 - - ai 40s - - union TUI mockup
每一行会话都以拥有该会话的工具开头——cc- 表示 Claude Code,cu- 表示 Cursor——后面依次显示模型、上下文进度条、当前等待方(you 或 ai)及等待时长、子 Agent 数量、工作树状态,以及正在执行的任务。
下面的短环境循环展示的是同一个程序处于空闲状态时的样子——这也是它绝大多数时间的运行状态:
两者都是真实、未经修改的 legbar,读取的是一个预置的 Agent 队列——有关其构建方式和重新录制方法,请参阅 demo/。第二个冲突行尤其值得关注:一个 Claude 会话和一个 Cursor agent 位于同一工作副本中。Cursor 不会写入会话标记或占用声明,因此,如果仪表盘只读取 Claude 的会话目录,根本无法发现这一冲突。
SESSIONS ——机器上的每个实时 Agent。Claude Code 会话通过 pid 与 ~/.claude/sessions/<pid>.json 关联;模型、上下文消耗和状态从会话自身的 JSONL 转录记录中读取。Cursor agents 也会显示,其名称带有 cu- 前缀——Cursor 不会写入会话标记或占用声明,因此,只读取 Claude 会话目录的队列视图将无法看见旁边运行的任何 Cursor Agent。
CI / PRS ——所有克隆仓库中的 GitHub Actions 运行状态和开放 Pull Request;失败会被固定显示,因此红色构建状态不会被滚动隐藏。
Python 3.9+,仅使用标准库。支持 macOS、Linux 和 Windows。
legbar 也会基于同一个发行版本自动发布到其他几个渠道:
pip install legbar # 如果你宁愿不使用 pipx npm install -g legbar # 反正机器上通常已经有 Node brew install gmhoward9289-ops/tap/legbar # macOS / Linux winget install gmhoward9289-ops.legbar # Windows
Debian 和 Ubuntu 可以添加已签名的 apt 仓库,而不是一次性安装 .deb:
curl -fsSL https://gmhoward9289-ops.github.io/legbar/legbar-archive-keyring.asc
| sudo gpg --dearmor -o /usr/share/keyrings/legbar-archive-keyring.gpg
echo "deb [signed-by=/usr/share/keyrings/legbar-archive-keyring.gpg]
https://gmhoward9289-ops.github.io/legbar stable main"
| sudo tee /etc/apt/sources.list.d/legbar.list
sudo apt update && sudo apt install legbar
没有包管理器的 Windows 用户:可从最新版本下载冻结版 .exe zip 文件。
legbar # 全屏视图 legbar --once # 渲染一帧后退出(用于管道、CI、截图) legbar --json # 输出已关联的状态,可管道传给其他工具 legbar --no-git # 如果 git 探测较慢,则跳过 git 探测 legbar --no-ci # 跳过 gh 扫描(离线或扫描较慢时) legbar --waiting-alert 45 # 仅对等待超过 45 分钟的会话发出提醒
在全屏视图中:q 退出,g 切换 Git 探测,r 立即刷新。
NEEDS YOU 被刻意设计得难以忽略。对于一支需要你逐一处理的 Agent 队列而言,会话等待你输入是常见的静止状态,因此较短的等待会被列出,但不会标记或着色;只有等待时间超过 --waiting-alert(默认 20 分钟)时,才会显示 ! 和颜色,因为此时你大概已经忘记它了。冲突工作树不受此规则限制——它们造成的是工作成果损失,而不只是延迟,因此从第一帧起就会高亮警示。
所有覆盖配置均使用 LEGBAR_*。旧的 roost / leghorn / ccwork 变量名仍然有效,因此现有安装会继续保留既有配置;若两者同时设置,则新名称优先。
| 变量 | 默认值 | 指向内容 |
|---|---|---|
LEGBAR_REPOS_ROOT |
~/GitHub |
克隆仓库所在位置 |
LEGBAR_SESSIONS_DIR |
~/.claude/sessions |
实时会话标记 |
LEGBAR_PROJECTS_DIR |
~/.claude/projects |
会话转录记录 |
LEGBAR_CURSOR_HOME |
~/.cursor |
Cursor 的 Agent 转录记录 |
LEGBAR_CURSOR_MAX_IDLE_SECS |
86400 |
Cursor Agent 被视为实时的最长空闲回溯时间 |
LEGBAR_BACKENDS |
claude,cursor |
要运行哪些发现通道 |
Cursor 的存活状态是推断而来,而不是直接探测。 Claude 行表示 该进程存在(os.kill(pid, 0))。Cursor 行表示 该转录记录近期有更新——Cursor 不会写入可用于关联的 pid。这是较弱的信号,且界面明确如此标示;Cursor 行的 pid 为 None,而非人为编造。
Cursor 的项目 slug 存在信息损失。 该 slug 使用 - 连接路径片段,而 - 本身也可以出现在目录名中,因此 c-Users-me-dev-heron-ops 既可能表示 dev/heron/ops,也可能表示 dev/heron-ops。legbar 会根据磁盘上实际存在的路径,以最长优先的方式解析每一段。若某个 slug 无法解析到任何路径——例如来自另一台机器的检出副本,或已删除的克隆仓库——则会回退到朴素拆分,而不是报错。
Windows 控制台会导致块绘制字符出现乱码,因此上下文进度条、面板分隔线和状态字形都使用纯 ASCII。这也是 roost 的迷你趋势图和 leghorn 的表格所遵循的相同限制。
,__
_(o \__
/ \
| ====== | | ====== | \ ==== / ______/ || || ^^ ^^
legbar 会读取转录记录和注册表,并以只读模式运行 git 和 gh。它绝不会向仓库写入内容。
- roost ——面向 Claude Code 的
top:显示每个会话的上下文消耗、模型,以及会话创建的子 Agent。 - leghorn ——独立的仓库通道:将会话关联至工作树和真实 Git 状态、CI 以及提交动态。
- legbar ——通过同一发现层,在一个屏幕上呈现两条通道。
henhouse.py 就是这一发现层:会话、转录记录、Git、GitHub 和 Cursor。它本身也是一个可用的 CLI(python henhouse.py)。
MIT
English / 原文
One screen for the whole fleet: live agent sessions beside GitHub CI , drawn from a single discovery layer so the two panes can never disagree.
roost answers what are the models doing. leghorn answers what are the repos doing. Both are true at once and neither view contains the other — so watching a fleet has meant watching two windows and joining them by eye. legbar draws both lanes on one canvas.
legbar 5 sessions | 1 cursor | 1 need input | 15 ci red | 125k held | 18:37:00
NEEDS YOU GITHUB
--------- ------
!! CONTESTED heron-ops 2 sessions in one working copy: c5468eb1, heron~ X roost ci
! WAITING heron-ops-3c needs your reply -- 12m -- fix contested false~ X roost #56 ci: skip winget~
CI RED roost ci > leghorn release
WAITING ON YOU
--------------
!cc-heron-op~ FB5 ###------- 32% you 12m 3 ~2^1 fix contested false alarm
cc-swamp-op~ OP5 ##-------- 25% you 12m - ~1 draft discussions packet
WORKING NOW
-----------
cc-heron-op~ FB5 #--------- 10% ai 3s 2 clean survey henhouse drift
STARTING
--------
!cu-c5468eb1 - - ai 40s - - union TUI mockup
Each session row leads with the tool that owns it — cc- for Claude Code, cu- for Cursor — then model, context bar, who is pending (you or ai) and for how long, subagent count, working-tree state, and what it is doing.
The short ambient loop below is the same program, idling — which is how it spends almost all of its time:
Both are real legbar, unmodified, reading a staged fleet — see demo/ for how it is built and how to re-record. The second contested row is the one worth looking at: a Claude session and a Cursor agent in the same working copy. Cursor writes no session marker and no claim, so a dashboard reading only Claude's session directory cannot see that collision at all.
SESSIONS — every live agent on the machine. Claude Code sessions are joined by pid against ~/.claude/sessions/<pid>.json, with model, context burn, and status read from the session's own JSONL transcript. Cursor agents appear too , marked with a cu- name prefix — Cursor writes no session marker and no claim, so a fleet view that only reads Claude's session directory is blind to every Cursor agent running beside it.
CI / PRS — GitHub Actions runs and open pull requests across every clone, with failures pinned so a red build cannot scroll away.
Python 3.9+, standard library only. Works on macOS, Linux and Windows.
legbar also publishes to a few other channels, picked automatically off the same release:
pip install legbar # if you'd rather skip pipx
npm install -g legbar # Node's on the box already anyway
brew install gmhoward9289-ops/tap/legbar # macOS / Linux
winget install gmhoward9289-ops.legbar # Windows
Debian and Ubuntu can add the signed apt repo instead of a one-shot .deb:
curl -fsSL https://gmhoward9289-ops.github.io/legbar/legbar-archive-keyring.asc \
| sudo gpg --dearmor -o /usr/share/keyrings/legbar-archive-keyring.gpg
echo "deb [signed-by=/usr/share/keyrings/legbar-archive-keyring.gpg] \
https://gmhoward9289-ops.github.io/legbar stable main" \
| sudo tee /etc/apt/sources.list.d/legbar.list
sudo apt update && sudo apt install legbar
Windows without a package manager: grab the frozen .exe zip from the latest release.
legbar # the full-screen view
legbar --once # render one frame and exit (pipes, CI, screenshots)
legbar --json # the joined state, for piping somewhere else
legbar --no-git # skip git probing if it is ever slow
legbar --no-ci # skip the gh sweep (offline, or when it is slow)
legbar --waiting-alert 45 # only shout about waits older than 45 minutes
In the full-screen view: q quit, g toggle git probing, r refresh now.
NEEDS YOU is deliberately hard to tune out. A session waiting on you is the normal resting state of a fleet you are working through one at a time, so a young wait is listed but unmarked and uncoloured; only one past --waiting-alert (default 20 minutes) takes the ! and the colour, on the theory that by then you have forgotten it. Contested trees are exempt — they destroy work rather than delay it, and are loud from the first frame.
Every override is LEGBAR_*. The older roost / leghorn / ccwork variable names are still honoured, so an existing install keeps whatever it had configured; the new name wins when both are set.
| Variable | Default | What it points at |
|---|---|---|
LEGBAR_REPOS_ROOT |
~/GitHub |
where the clones live |
LEGBAR_SESSIONS_DIR |
~/.claude/sessions |
live-session markers |
LEGBAR_PROJECTS_DIR |
~/.claude/projects |
session transcripts |
LEGBAR_CURSOR_HOME |
~/.cursor |
Cursor's agent transcripts |
LEGBAR_CURSOR_MAX_IDLE_SECS |
86400 |
how far back a Cursor agent counts as live |
LEGBAR_BACKENDS |
claude,cursor |
which discovery lanes run at all |
Cursor liveness is inferred, not probed. A Claude row means this process exists (os.kill(pid, 0)). A Cursor row means this transcript moved recently — Cursor writes no pid to join against. That is a weaker signal and it is labelled as one; pid is None for Cursor rows rather than invented.
Cursor's project slugs are lossy. The slug joins path parts with -, and - is legal inside a directory name, so c-Users-me-dev-heron-ops reads equally as dev/heron/ops and dev/heron-ops. legbar resolves each segment longest-first against what actually exists on disk. A slug that resolves nowhere — another machine's checkout, a deleted clone — falls back to the naive split rather than raising.
Block-drawing characters mojibake in the Windows console, so the context bars, the pane rules and the status glyphs are all plain ASCII. Same constraint roost's sparklines and leghorn's tables are built around.
,__
_(o \__
/ \
| ====== |
| ====== |
\ ==== /
\______/
|| ||
^^ ^^
legbar reads transcripts and registries, and runs git and gh in read-only modes. It never writes to a repo.
- roost —
topfor Claude Code: per-session context burn, models, and the subagents a session spawned. - leghorn — the repo lane on its own: sessions joined to worktrees and real git state, CI, and a commit feed.
- legbar — both lanes on one screen, over one discovery layer.
henhouse.py is that discovery layer: sessions, transcripts, git, GitHub, and Cursor. It is a working CLI in its own right (python henhouse.py).
MIT

