内容
<div align="center">
<img src="images/rook-2.png" alt="rook" width="620" />
### A coding agent that lives in your terminal
<p>
<a href="https://github.com/martian56/rook/actions/workflows/ci.yml"><img alt="CI" src="https://github.com/martian56/rook/actions/workflows/ci.yml/badge.svg" /></a>
<a href="https://github.com/martian56/rook/releases/latest"><img alt="Latest release" src="https://img.shields.io/github/v/release/martian56/rook?sort=semver&label=release&color=5b4fe8" /></a>
<a href="LICENSE"><img alt="License: MIT" src="https://img.shields.io/badge/license-MIT-5b4fe8" /></a>
<a href="https://github.com/martian56/raven"><img alt="Built with Raven" src="https://img.shields.io/badge/built%20with-Raven-5b4fe8" /></a>
<img alt="Platforms" src="https://img.shields.io/badge/platform-linux%20%7C%20windows-8891a5" />
</p>
</div>
rook streams a real model's reply token by token, and the model can read,
search, edit files, and run commands in your working directory, with you
approving anything that changes the repo. It is built on the
[plumage](https://github.com/martian56/plumage) TUI framework and the
[aviary](https://github.com/martian56/aviary) model gateway, so it speaks to
OpenAI, Anthropic, Gemini, and a dozen more providers behind one API.
The name: a rook is the raven's cousin, which is what this is to the Raven
language.
**Contents:**
[Install](#install) · [Run it](#run-it) · [Talking to it](#talking-to-it) · [Models](#choosing-a-model) · [Tools](#tools) · [Commands](#commands) · [Skills & memory](#skills-and-memory) · [Subagents](#subagents) · [Web](#web) · [Git](#git) · [Plugins](#plugins) · [Hooks](#hooks) · [MCP](#mcp) · [How it is built](#how-it-is-built) · [Development](#development)
## Install
Download a build for your platform from the
[latest release](https://github.com/martian56/rook/releases/latest):
| Platform | File |
|----------|------|
| Windows | `rook-<version>-x86_64.msi` (adds rook to your PATH) or `rook-<version>-x86_64.zip` |
| Debian / Ubuntu | `rook_<version>_amd64.deb` |
| Fedora / RHEL | `rook-<version>-1.x86_64.rpm` |
| Linux (any) | `rook-<version>-x86_64.tar.gz` |
Or run it from source with the [Raven toolchain](https://github.com/martian56/raven):
```
git clone https://github.com/martian56/rook
cd rook
rvpm run
```
## Run it
Launch it in a real terminal, `rook` if you installed a release, or
`rvpm run` from a source checkout, then give it an API key. Either export
one:
```
export OPENROUTER_API_KEY=... # or OPENAI_API_KEY, ANTHROPIC_API_KEY, ...
```
or type **`/key`** in the app and paste the key for the current provider. A
key entered that way is saved to `~/.rook/auth.json` and reused next time.
OpenRouter is the default provider, since one key there reaches most models.
<div align="center">
<img src="images/welcome.png" alt="rook's welcome screen" width="840" />
</div>
## Talking to it
- Type a message and press Enter. The reply streams in.
- Type `@` to pin a file to the message: a picker fuzzy-matches paths as
you type, arrows move, Tab or Enter completes. On send, every
`@path` you referenced is read and attached, so the model has those
files without a separate read step.
- The model uses tools as it works. Reading and searching happen
automatically; a file write, edit, or shell command pauses for your
approval: **y** to allow, **a** to allow every call of that kind for the
rest of the turn, **n** to deny (the denial is fed back to the model).
A file change shows its diff right in the approval prompt, removals
red, additions green, and again under the tool row once it runs, so
you see exactly what changed.
- **Esc** interrupts; **ctrl+c** twice quits. **PageUp/PageDown** or the
mouse wheel scroll.
- **Drag with the left mouse button** to select transcript text; it is
copied to your clipboard on release. You can scroll while dragging, and
dragging past the top or bottom edge extends the selection. (rook draws
its own selection because it captures the mouse for scrolling; a click
or any keypress clears it.)
- The status bar shows the session's token usage and an estimated cost;
each turn also reports its own tokens and cost when it finishes. Costs
are rough per-model estimates for at-a-glance spend, not billing.
## Choosing a model
Models are `provider/model` strings (aviary's format).
- `/model` opens a picker with a search bar: type to filter the
catalog (the mid-2026 flagships and the models topping the OpenRouter
usage charts), arrow-select and Enter. Your choice is remembered for
next time.
- `/model anthropic/claude-sonnet-5` sets one directly; any
`provider/model` string aviary can route works, listed or not.
- The startup model is resolved in order: the `--model` flag
(`rvpm run -- --model openai/gpt-4o`), `ROOK_MODEL`, a project
`rook.json`, a global `~/.config/rook/rook.json`, the last model you
picked, then a built-in default.
`rook.json` is a small JSON file:
```json
{ "model": "openai/gpt-4o", "base_url": "" }
```
`base_url` (or `ROOK_BASE_URL`) points at any OpenAI-compatible endpoint,
for a local or self-hosted model.
The provider's key comes from its environment variable
(`OPENROUTER_API_KEY`, `OPENAI_API_KEY`, `ANTHROPIC_API_KEY`, and so on), or
from a key you entered with `/key` (stored in `~/.rook/auth.json`). Picking a
model whose provider has no key opens the key prompt automatically.
## Tools
The model can call:
- `read_file`, `list_dir`, `file_tree`, `grep` (read-only, run
automatically)
- `write_file`, `edit_file`, `multi_edit`, `run_command`,
`run_background` (mutating, approved by you)
`multi_edit` applies several find-and-replace edits to one file in a
single call, in order and all or nothing: if any `old_text` is missing,
nothing is written. A multi-spot change is one approval, and the prompt
shows the combined diff before you allow it.
File paths accepted by tools and `@` mentions are normalized inside the
workspace. Absolute paths, paths that escape with `..`, and symlinked path
segments are rejected.
`run_background` starts a long-running command (a dev server, a
watcher, an app rook just built) and returns a shell id immediately
instead of blocking; the output collects in the background. The model
follows up with `read_shell` (what a shell printed since its last
look), `list_shells` (status, runtime, and command of each), and
`kill_shell` (stop one; this asks for approval). So rook can start the
app it just built, watch the log, and react to what it sees. Stored
output is capped so a chatty process cannot grow memory without bound,
old finished shells fall off the list, and quitting rook kills
everything still running so no child is orphaned.
`/plan` toggles plan mode: the model may read, search, and inspect but
its write, edit, and command tools are withheld, so it studies the task
and proposes an ordered plan instead of changing anything. The status
bar shows a `◆ PLAN` badge while it is on. Review the plan, then `/plan`
again to carry it out. Subagents dispatched in plan mode are read-only
too.
During multi-step work the model keeps a checklist with `set_todos`,
shown live above the input: done steps check off dim, the current one
is highlighted, pending ones wait. `/clear` empties it.
When a decision is yours to make (which approach, which of several
fixes), the model asks with `ask_user`: a modal shows the question and
its options, arrows pick, Enter answers, Esc declines. The pick goes
back to the model as text.
`run_command` runs through the platform shell in the working directory and
returns stdout, stderr, and the exit code. Foreground commands time out after
120000 ms by default, and Esc interrupts the active command as well as the
model stream. Tool output is truncated so a noisy command cannot bury the
answer.
## Commands
Type `/` and a menu of every command opens above the input, filtered as
you keep typing: arrow keys move the highlight, **Tab** completes the
name, **Enter** runs the selection, **Esc** dismisses. Custom commands
from `.agents/commands/` appear right in the menu.
`/shells` opens a panel of the background shells, id, status with
runtime or exit code, and command, refreshed live while it is open.
Enter tails the highlighted shell: a full-screen pane follows its
output as it is produced, so a dev server or build log is readable
while rook keeps working. Esc steps back.
`/sessions` lists your past conversations (newest first) and resumes
one: the transcript comes back and the model picks up the context.
Sessions save to `~/.rook/sessions` automatically after each turn;
`/clear` starts a fresh one and leaves the old one resumable.
`/permissions` opens a toggle menu for common grants like file edits,
shell commands, background shells, git commits, and MCP tools. Choices
are saved to your global `~/.agents/settings.json`, not the project, and
deny rules stay in place.
When a long conversation nears the model's context window, rook
compacts it: the older turns are summarized into a compact note (by a
one-off model call) and the recent turns are kept verbatim, so the
session keeps going instead of overflowing or getting truncated
blindly. A notice says when it happens. The transcript you see is
untouched; only what the model receives is condensed. If the summary
call fails, the conversation is left as is.
`/help` opens the same list as a menu: arrows to browse every command
(built-in and custom) with its description, Enter to run one, Esc to
close. The other built-ins: `/clear` (wipe the conversation), `/model`,
`/theme` (pick a color theme; arrow keys preview it live, and the
choice is remembered), `/key` (set the current provider's API key),
`/permissions`, `/quit`.
Built-in themes: Rook and Rook Light, Dracula, Gruvbox Dark and Light,
Nord, Solarized Dark and Light, Catppuccin Mocha and Latte, Tokyo Night.
`/theme nord` sets one directly. With no theme chosen yet, rook starts
with the dark or light default matching the terminal background (read
from `COLORFGBG` where the terminal sets it). On terminals without
truecolor, theme colors are downsampled to the 256-color cube or the
basic 16, judged from `COLORTERM` and `TERM`.
Your own palettes go in `.agents/themes/<name>.json` (project or
global) and appear in the picker alongside the built-ins:
```json
{
"name": "Midnight",
"accent": "#7aa2f7",
"dim": "#565f89",
"text": "#c0caf5",
"tool": "#9ece6a",
"warn": "#e0af68",
"error": "#f7768e"
}
```
Six colors define a palette; rook maps them onto every UI element the
same way it does for the built-ins. A palette whose name collides with
an existing theme is skipped.
## Skills and memory
rook reads the cross-agent `.agents` layout: a project `./.agents` and a
global `~/.agents`, with project entries winning. A skill is a folder
`.agents/skills/<name>/` holding a `SKILL.md`, frontmatter with a `name`
and one-line `description`, then a markdown body of instructions. The
model sees an index of skill names and descriptions in its system
prompt, and pulls in a skill's full instructions with the `use_skill`
tool when one matches the task (shown in the transcript like any other
tool call).
An `AGENTS.md` in the working directory (the cross-tool memory file:
build steps, tests, conventions) is loaded into the system context on
every turn, along with a global `~/.agents/AGENTS.md` for your own
standing notes. The global file comes first so the project one can
refine it.
`.agents/settings.json` (project or global) configures rook alongside
`rook.json`:
```json
{
"model": "openai/gpt-4o",
"theme": "Nord",
"base_url": "",
"permissions": {},
"tools": {
"run_command": { "timeout_ms": 120000 }
},
"mcp": {}
}
```
The string fields join the resolution chain (a root's `rook.json` wins
over the same root's settings, and project beats global). The `tools`
section configures built-in tool behavior, and the `mcp` section configures
MCP servers.
Global user settings and installed plugins are trusted roots. Project
`.agents` settings are read more carefully: deny rules apply, but allow
rules, hooks, and MCP server commands are ignored unless you opt in from
your global `~/.agents/settings.json`:
```json
{
"trust": { "project_settings": true }
}
```
That switch trusts project settings for every project, so only enable it
when that is the behavior you want.
`permissions` is live: allow rules skip the approval prompt for calls
you always trust, deny rules block calls outright (for any tool, even
read-only ones), and deny beats allow. Type `/permissions` to grant
common allow rules from the app. A rule is a tool name, a tool-name glob
such as `mcp__*`, or a tool name with a glob matched against the call's
command or path:
```json
{
"permissions": {
"allow": ["run_command(rvpm *)", "read_shell"],
"deny": ["run_command(rm *)", "read_file(*secrets*)"]
}
}
```
Deny rules from the project and global `.agents` both apply, and they
bind subagents the same way. Allow rules from global settings and
installed plugins can skip approval. Project allow rules only skip
approval after project settings are trusted. Anything not covered falls
through to the normal approval prompt.
Custom slash commands live in `.agents/commands/<name>.md`: optional
frontmatter with a `description` (shown by `/help`), then a prompt
template. `/name args` sends the template with `$ARGUMENTS` replaced by
`args` (or the args appended when the template has no placeholder). The
transcript shows what you typed; the model gets the expansion. Built-in
commands cannot be overridden.
## Subagents
Three come built in, all read-only: **explorer** (scout the codebase
and report), **reviewer** (critique code and list real defects), and
**planner** (produce a step-by-step plan). Ask rook to "have the
explorer find where X happens" and it delegates.
Define your own in `.agents/subagents/<name>.md`: frontmatter with a
`description`, an optional `tools` allowlist (comma-separated), and an
optional `model` override, then the agent's system prompt as the body.
A custom subagent is read-only by default: omit `tools` and it can only
read and search (`read_file`, `list_dir`, `file_tree`, `grep`,
`git_status`, `git_diff`). To grant more, name the exact tools it may
call, or write `tools: all` to give it every tool. The roster the model
sees lists each subagent's effective access. The model delegates with
the `dispatch` tool; the subagent runs an
isolated conversation (its own prompt, tools, and rounds) and only its
final answer returns to the main conversation. While it works, its
activity shows as a live nested block in the transcript, a `◆ name
agent working…` header with the agent's tool calls indented beneath it
(parallel agents each keep their own block), and when it finishes the
block collapses to one `done · N tools` line ahead of the result.
Anything mutating still stops for your approval, labeled with the
agent's name (parallel agents queue for the prompt one at a time).
Subagents cannot dispatch further agents. A definition named after a
built-in replaces it.
When the model dispatches several agents in one step they run in
parallel, each on its own goroutine with its own conversation, and the
main agent continues once every result is back, wide read-only work
like searching three areas at once finishes in one round.
## Web
`web_search` returns the top results (titles and links) for a query,
and `web_fetch` reads a URL as text with the HTML stripped, so the
model can pull in current documentation during a task. Both are
read-only and run automatically; output is truncated like other tools.
## Git
rook is git-aware. `git_status` and `git_diff` (read-only, auto-run) let
the model see the branch and the working tree. `git_commit` commits only
changes that are already staged, and its approval prompt shows the
status, any untracked files (which it never commits), and the exact
staged diff before it runs.
## Plugins
A plugin is a shareable `.agents` bundle: a git repo with a
`plugin.json` (name, version, description) and the same `skills/`,
`subagents/`, `commands/`, and `themes/` folders rook reads from
`.agents`. Installed plugins live under `~/.rook/plugins/<name>/`.
An installed plugin is read like another `.agents` root, so its
skills, subagents, commands, and themes merge into the session
automatically, with precedence project `.agents` > plugin > global
`.agents`. Manage them with `/plugins`: `list` shows what is installed
and what each contributes, `add <git-url> [tag]` installs one, `remove
<name>` deletes one, and `update <name>` re-installs from the recorded
source. `browse [query]` lists plugins from a git-hosted index so you
can find one without knowing its URL, and `add <name>` then installs a
plugin by its index name. The index URL defaults to a martian56-hosted
list and is overridable with `ROOK_PLUGIN_INDEX`.
## 钩子
钩子在会话中发生某些事件时运行命令。在任何根目录下 `settings.json` 文件中 `hooks` 关键字下声明它们,文件路径可以是项目 `.agents` 目录、已安装的插件或全局 `~/.agents` 目录,按事件键入:
```json
{
"hooks": {
"pre-tool": [{ "match": "write_file", "command": "./deny-secrets.sh" }],
"post-tool": [{ "command": "git add -A" }],
"turn-end": [{ "command": "notify-send 'rook is done'" }]
}
}
```
项目钩子仅在项目设置被信任后运行。全局设置和已安装插件的钩子可以在没有额外确认的情况下运行。
事件包括 `session-start`、`pre-tool`、`post-tool`、`pre-prompt` 和 `turn-end`。`match` 是工具名称的 glob(默认为 `*`);它仅适用于工具事件。每个钩子的命令都通过平台 shell 运行,并带有 stdin 上的小 JSON 上下文:`{ "event", "tool", "args" }`,其中 `args` 是工具调用的原始参数。退出状态非零的 `pre-tool` 钩子会阻止工具,其输出会作为原因反馈给模型;其他事件都是只读的。因为插件只是另一个根目录,所以插件可以通过相同的方式提供钩子。
工作示例位于 [`examples/hooks/`](examples/hooks/):阻止危险命令、在编辑后格式化文件、在回合结束时通知,并附有可复制的 `settings.json` 文件。
## MCP
rook 是 MCP 客户端:它启动模型上下文协议服务器,并使用它们提供的工具、资源和提示。在任何根目录下 `settings.json` 文件中 `mcp` 关键字下配置服务器,文件路径可以是项目 `.agents` 目录、已安装的插件或全局 `~/.agents` 目录:
```json
{
"mcp": {
"servers": [
{
"name": "filesystem",
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-filesystem", "."],
"env": ["SOME_TOKEN=value"]
}
]
}
}
```
每个服务器条目包含 `name`、`command`、`args` 和 `env`,其中 `env` 是 `"KEY=value"` 字符串列表。项目 MCP 服务器在项目设置被信任之前被忽略。全局设置和已安装插件的服务器在首次使用时或运行 `/mcp connect` 命令时连接。
- **工具** 服务器提供的工具通过 `mcp__<server>__<tool>` 方式访问。由于是外部工具,调用时总是需要确认。
- **资源** 是可读上下文。模型使用 `mcp_read_resource` 工具拉取资源,该工具无需确认即可运行,因为它只读。
- **提示** 是服务器提供的模板,可以通过 `/mcp prompt <server> <name> [key=value ...]` 命令调用;展开的提示作为一个回合运行。
`/mcp` 命令显示已配置的服务器、连接状态和提供的服务;`/mcp connect` 命令在后台启动连接。
两个平台注意事项。每个服务器的 `env` 在 Unix 上通过 `env` 命令应用;在 Windows 上,服务器继承 rook 的环境,因此在那里设置变量。在 Windows 上,`npx` 等 `.cmd` 启动器不会直接找到,因此使用 `"command": "cmd", "args": ["/c", "npx", ...]`。
## 构建
rook 是一个 plumage 应用。一个有趣的问题是流式完成会阻塞,而 UI 必须继续绘制;每个回合都在后台 goroutine 上运行,该 goroutine 产生有序的显示事件日志并拥有对话,由互斥锁保护;plumage 循环在每个 tick 时清空并重放该日志。审批是一个单槽通道,goroutine 在 UI 渲染提示时阻塞。
```
src/
main.rv 入口:构建应用并运行
app/ 模型、更新(事件、键、审批)、视图
agent/ 回合循环、共享状态、会话
agents/ .agents 文件夹加载器(技能、命令、设置)
tools/ 文件、搜索和 shell 工具,以及模式注册表
config/ 模型解析、rook.json、/model 目录
ui/ 转录渲染器、主题和旋转器
plugins/ 安装、加载和管理可共享的 .agents 包
hooks/ 在生命周期事件上运行命令
mcp/ MCP 客户端:传输、连接、工具、资源
commands.rv 斜杠命令解析
```
## 开发
```
rvpm test # 42 个测试:工具、配置、命令和端到端回合
# (流式传输、工具调用和审批)针对本地服务器
rvpm build
rvpm fmt
```
端到端测试驱动一个完整的回合,针对一个作为模型的进程内服务器,因此测试套件不需要网络和密钥。
## 已知限制
grep 是字面字符串匹配,而不是正则表达式。子代理自己的请求(非流式)在下一个工具回合时停止,而不是在飞行中。
## 许可证
MIT
MCP 配置
以下是此 MCP Server 的配置信息,可直接复制到 Cursor 或其他 MCP 客户端中使用。
mcp.json
连接信息
猜你喜欢
暂无推荐服务器