Metadata-Version: 2.4
Name: heng-agent
Version: 0.5.0
Summary: 中文优先的终端编码智能体：读代码、改代码、跑命令；支持 DeepSeek、Kimi、通义、GLM、Claude 等，兼容 Claude Code 配置
Author: 抓蛙师
License-Expression: Apache-2.0
Keywords: ai,agent,coding-agent,cli,claude-code,deepseek,llm
Classifier: Development Status :: 4 - Beta
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: Natural Language :: Chinese (Simplified)
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Software Development
Requires-Python: >=3.11
Description-Content-Type: text/markdown
License-File: LICENSE
License-File: NOTICE
Requires-Dist: httpx[socks]>=0.27
Requires-Dist: rich>=13
Requires-Dist: prompt_toolkit>=3.0
Requires-Dist: pydantic>=2.6
Requires-Dist: pillow>=10
Requires-Dist: agent-client-protocol<0.13,>=0.12.1
Provides-Extra: dev
Requires-Dist: pytest>=8; extra == "dev"
Requires-Dist: ruff>=0.6; extra == "dev"
Dynamic: license-file

<img src="https://raw.githubusercontent.com/bkywksj/heng-agent/master/docs/brand/logo-256.png" width="96" alt="heng-agent">

# heng-agent

类似 Claude Code 的终端编码智能体：用中文派活，它读代码、改代码、跑命令，直到任务完成。
支持 Anthropic 与 OpenAI 两种协议，内置 DeepSeek、Kimi、GLM、通义千问、OpenAI、OpenRouter、Ollama 与 heng 自己的模型，
也能接任意兼容中转站。

## 安装

一条命令装好（没有 uv 会先自动装 uv；pypi.org 连不上会自动改用清华镜像；已装过就升级到最新版）。
有新版本时欢迎页会提示，运行 `heng-agent upgrade` 升级（每天最多后台查一次，可用 `settings.update_check` 关掉）：

```powershell
# Windows（PowerShell）
irm https://gitee.com/bkywksj/heng-agent/raw/master/install.ps1 | iex
```

```bash
# macOS / Linux
curl -LsSf https://gitee.com/bkywksj/heng-agent/raw/master/install.sh | sh
```

（在国外把地址换成 `https://raw.githubusercontent.com/bkywksj/heng-agent/master/install.ps1`、`…/install.sh`。）

已经有 [uv](https://docs.astral.sh/uv/)（Python 的包管理工具，会自动准备好 Python）的话，也可以直接：

```bash
uv tool install heng-agent      # 装成全局命令，任何目录都能敲 heng-agent
heng-agent upgrade              # 升级（Windows 上会开个新窗口、等 heng-agent 退出后再升级）
uv tool uninstall heng-agent    # 卸载
```

从源码装：`git clone` 本仓库后，在仓库目录里 `uv tool install .`。
装完如果提示「not on your PATH」，运行一次 `uv tool update-shell` 再重开终端。

**第一次运行**会引导你配置模型服务：先自动找电脑上现成的配置（环境变量里的 `DEEPSEEK_API_KEY` 等密钥、
Claude Code 里配的中转站、Codex 的 `~/.codex/config.toml` 里用 API key 的服务商与 `codex login --api-key` 存的密钥），
能一键用上；没有就选服务商、填密钥。配好后自动测一下连接，失败会说清楚原因（密钥不对、余额不足、连不上）。
随时可以用 `/config provider` 修改。

> Claude 订阅（Pro / Max）、ChatGPT 账号的登录**不能**拿来在 heng-agent 里用：订阅账号的登录令牌只给官方客户端用，
> 第三方读出来调接口违反服务条款，可能导致封号。heng-agent 只用 API key。想用订阅额度，就直接用 Claude Code / Codex。

### 平台支持

主要在 Windows（Windows Terminal）上开发与测试；macOS、Linux 上核心功能（对话、工具、MCP、钩子、会话……）
都能用，以下几项暂时只在 Windows 上有：

| 功能 | Windows | macOS / Linux |
|---|---|---|
| AI 回复时按 ESC 中断、Ctrl+B 转后台 | ✅ | 暂不支持，用 Ctrl+C 中断 |
| Alt+V 粘贴剪贴板里的图片、文件 | ✅ | 暂不支持，用 `@文件路径` |
| Shift+Enter 换行 | ✅ | 取决于终端；Ctrl+J、Alt+Enter 处处可用 |

## 最快上手（以 DeepSeek 为例）

```bash
export DEEPSEEK_API_KEY=你的密钥                # PowerShell：$env:DEEPSEEK_API_KEY="..."
cd 你的项目目录
heng-agent --provider deepseek
```

## 服务商

`heng-agent --list-providers` 列出全部配置档、默认用哪个、密钥是否已设置（只显示已设置 / 未设置，不显示密钥）。

| 名字 | 协议 | 密钥环境变量 | 说明 |
|---|---|---|---|
| `heng` | anthropic | `HENG_AGENT_API_KEY` | 本机 heng serve（自己的模型或 proxy 转发），**默认** |
| `anthropic` | anthropic | `ANTHROPIC_API_KEY` | Anthropic 官方 |
| `deepseek` | anthropic | `DEEPSEEK_API_KEY` | DeepSeek |
| `kimi` | anthropic | `MOONSHOT_API_KEY` | Kimi（月之暗面） |
| `glm` | anthropic | `ZHIPU_API_KEY` | 智谱 GLM |
| `qwen` | openai | `DASHSCOPE_API_KEY` | 通义千问（阿里云百炼） |
| `openai` | openai | `OPENAI_API_KEY` | OpenAI |
| `openrouter` | openai | `OPENROUTER_API_KEY` | 一个密钥用多家模型 |
| `ollama` | openai | 不需要 | 本机 Ollama |

预设里的模型名只是建议值（各家改名很频繁），用 `--model` 临时换，或在配置文件里改。
界面里随时 `/provider deepseek` 切换服务商（对话历史保留），`/model 名字` 换模型。

### 配置文件 `~/.heng-agent/config.json`

自己的中转站、改默认服务商、改预设的模型名都写在这里：

```json
{
  "default": "deepseek",
  "profiles": {
    "deepseek": {"preset": "deepseek", "model": "deepseek-flash"},
    "永夜": {
      "protocol": "anthropic",
      "base_url": "https://你的中转站地址",
      "model": "claude-opus-4-8",
      "api_key": "sk-..."
    }
  }
}
```

- `preset`：继承一个内置预设，只写要改的字段。
- 密钥二选一：`api_key_env`（读环境变量，推荐）或 `api_key`（写在这个文件里；文件只在你的用户目录，不会进任何项目）。
- `auth`：密钥放哪个请求头，`auto`（默认，两种都带）/ `x-api-key` / `bearer`。中转站报 401 时试试改这个。
- **代理**：默认按 `HTTP_PROXY` / `HTTPS_PROXY` 等环境变量走。要单独指定，在 `settings` 里写 `"proxy"`
  （管模型请求、MCP 的 http 连接、web_fetch），或在某个配置档里写 `"proxy"`（只管这个服务商，优先于 `settings`）。
  取值：代理地址 `http://主机:端口`、`socks5://主机:端口`，或 `direct`（不走代理，环境变量设了也不用）。
  例如国外的走代理、国内的直连：`"settings": {"proxy": "http://127.0.0.1:7890"}`，再给 `deepseek` 配置档写 `"proxy": "direct"`。
  本机地址（localhost、127.0.0.1）始终直连；代理只能写在用户配置里，项目配置写了会报错（别人的仓库不能替你决定请求发到哪）。
  `/doctor` 会显示当前实际走的代理。

**不支持 Claude 订阅账号登录（OAuth）**：Anthropic 的条款只允许订阅账号的登录凭据用在它自己的客户端里，
第三方工具使用有封号风险。用 Claude 请用 API 密钥（`anthropic` 预设）或中转站。

## 接自己的模型（heng）

```bash
# 终端 1：在 heng 模型仓库的目录启动模型服务
.venv/Scripts/heng.exe serve configs/serve/heng-mini.yaml          # 自己训练的模型
# 或 configs/serve/proxy-claude.yaml（需 HENG_UPSTREAM_API_KEY），把请求转发到 Claude

# 终端 2：在项目目录
heng-agent --provider heng --model heng-mini-0.1
```

## 常用参数

| 参数 | 作用 |
|---|---|
| `--provider 名字` | 用哪个服务商配置档 |
| `--model` / `--base-url` | 临时覆盖模型名 / 地址 |
| `--resume` | 接着这个目录上次的会话聊 |
| `-p "任务"` | 非交互：执行完这一个任务就退出（需要确认的操作一律拒绝） |
| `--permission-mode ask` | 默认，手动确认：改文件、跑命令前都问你 |
| `--permission-mode accept-edits` | 自动改文件：改文件不问，跑命令还问 |
| `--permission-mode plan` | 计划模式：只读代码，交出计划等你批准，批准后再动手（见下文「计划模式」） |
| `--permission-mode auto` | 全部放行：什么都不问，直接执行（相当于 Claude Code 的 bypass permissions；只在 CI、一次性沙箱等可信环境用；仍不能读写工作目录以外） |
| `--workdir` | 指定工作目录（默认当前目录） |

## 界面里

- 输入框：**Enter 发送，Shift+Enter 换行**（其他终端里用 Ctrl+J / Alt+Enter），`/` 补全命令，`@` 补全文件路径，
  Shift+Tab 切换权限模式（边框颜色跟着变）。
- **底部状态栏**两行：第一行是项目名与 git 分支（`*` = 有没提交的改动）· 服务商与模型 · MCP · 上一次的输出速度（低于 15 t/s 标橙色，多半是中转站拥堵或限流）·
  上下文进度条 · 额度；第二行是权限模式与提醒（后台任务、快到自动压缩）。窗口窄时第一行按
  额度 → 速度 → 分支 → 服务商名 → token 数 → 进度条的顺序省掉，不会截断。
  - **MCP**：`⠹ MCP 3` 橙色 = 还在连（数字是已连上的个数），`✓ MCP 6` 绿色 = 都连上了，`✗ MCP 5` 红色 = 有连不上的
    （`/mcp` 看原因）。三种写法一样宽，连接过程中状态栏不跳动。
  - **额度**：按服务地址认出服务商，用同一把 API key 查（每 3 分钟最多一次，后台查、不拖慢输入）：
    DeepSeek、Moonshot、硅基流动显示余额；Kimi Code 显示 5 小时与本周期剩几次；智谱 GLM Coding Plan 显示
    5 小时已用百分比与重置倒计时；new-api / one-api 一类中转站显示余额（不限额度的显示已用多少）。
    查不到的（本机服务、Anthropic 官方订阅要登录令牌、OpenRouter 要管理密钥）就不显示。
- **自定义状态栏**：在用户配置里写一条命令，它的输出替换状态栏第一行（只认用户配置，项目配置里写了不生效——它会执行命令）：

  ```json
  {"settings": {"status_line": "node ~/my-statusline.js"}}
  ```

  命令从标准输入收到会话信息的 JSON（字段同 Claude Code 的 statusLine：`model`、`workspace`、`cwd`、`session_id`、
  `context_window`，另有 `heng` 段：服务商、权限模式、输出速度），标准输出的前三行替换第一行，可以带 ANSI 颜色；
  每问答完刷新一次，超过 5 秒没结束算失败；MCP 状态挪到第二行。给 Claude Code 写过状态栏脚本的，
  写 `"status_line": "claude"` 就直接用 `~/.claude/settings.json` 里的 `statusLine`。不写就是上面的内置两行。
- **拖入文件 / 粘贴截图**：消息里出现的文件绝对路径（拖入文件、**智码终端里 Ctrl+V 粘贴的截图**都是这样进来的）
  发送时自动变成附件；工作目录以外的文件先复制到 `.heng-agent/attachments/`（自带 `.gitignore`，不进仓库）。
  在 Windows Terminal 里粘贴截图用 **Alt+V**：Windows Terminal 自己处理 Ctrl+V 且只粘文字，截图到不了程序
  （Claude Code 在 Windows 上也是 Alt+V）；把 Ctrl+V 交给程序的终端里 Ctrl+V 也能直接粘截图。
- **/config**：在对话里查看与修改配置，改完立即生效。`/config provider` 引导式添加服务商（自动取模型列表让你挑、
  密钥输入不回显）；`/config set profiles.yongye.model claude-opus-5`、`/config set settings.permission_mode plan`；
  `/config edit` 用记事本打开配置文件。改错了自动恢复原配置。加 `--project` 改项目配置。
- 配置文件的 `settings` 段可以写启动默认值：`permission_mode`、`max_tokens`、`max_rounds`、`bash_timeout`、
  `context_window`、`compact_ratio`、`image_preview`（命令行参数优先）。
- **图片缩略图**：附图发送后，在 Windows Terminal（1.22 起）里直接画出缩略图（Sixel）。`image_preview`：
  `auto`（默认，只在 Windows Terminal 里画）/ `on` / `off`；不支持 Sixel 的终端会显示成一屏乱码，所以默认不在别处画。
- **会话**：`/resume` 弹出这个目录的会话列表选一个接着聊（`/resume 关键词` 按会话名、第一句话筛选）；`/rename 名字`
  给会话起名；启动时 `heng-agent -c` 直接接最近的会话。
- **模型**：`/model` 向服务商取可用模型、方向键选，当前会话立即生效，可以顺手存成默认。
- **计划模式**：大改动先 Shift+Tab 切到 `plan`（或 `/mode plan`）再说任务。它只读代码、想清楚后交出计划
  （改哪些文件、怎么改、怎么验证），完整显示给你选：**开始执行**（改文件、跑命令前问你，切到 `ask`）、
  **开始执行、改文件不问**（切到 `accept-edits`），或**继续规划**（留在计划模式，接着说要改哪里）。
  批准后它在同一轮里接着按计划做，不用再说一遍。编辑器里（ACP）同样弹这三个选项，模式下拉框跟着变。
- **权限规则**：确认框里选「以后都允许」，规则写进用户配置；`/permissions` 查看与增删，例如
  `/permissions allow bash(npm test)`、`/permissions deny bash(git push*)`。写法 `工具名` 或 `工具名(匹配内容)`，可用 `*`。
  **拒绝规则优先于一切**（auto 模式下也拒绝）；**bash 组合命令（`&&` `;` `|` 重定向、`$(...)` 等）不适用允许规则**，
  照常询问，免得 `bash(git status*)` 放过 `git status && rm -rf …`；**项目配置只能加拒绝规则**，别人的仓库没法给自己放开命令。
- **提示缓存**（Anthropic 协议默认开启）：系统提示词与对话历史命中缓存后按 0.1 倍计价，长对话省钱明显；`/cost`
  显示命中率。不想用就在配置档里写 `"prompt_cache": false`。
- **输入框快捷键**：Ctrl+R 搜历史输入（Enter 采用、接着改）；Ctrl+G 用外部编辑器写长消息（`$EDITOR`，没设用记事本；
  VS Code 写 `code --wait`）；Ctrl+T 显示 / 隐藏输入框上方的任务清单。
- **会话工具**：`/context` 看上下文被什么占着；`/diff` 看这次会话改过的文件；`/copy` 复制上一条回复的原文（`/copy 2` 复制倒数第二条；回复里有代码块时可以只复制其中一段）。回复顶格显示、行尾不带空格，代码块不铺背景，鼠标拖选复制出来也是干净的；
  `/export [路径]` 导出 Markdown；`/compact 要求` 按你的要求压缩（如「只保留数据库迁移相关的」）。
- **任务完成提醒**：任务跑超过 `notify_after` 秒（默认 30，0 关闭）结束时响铃，Windows Terminal 会闪任务栏。
- **记忆**：输入以 `#` 开头的一句话（如 `# 这个项目用 pnpm`）不发给模型，选记进项目或用户的 HENG.md，立即生效；
  `/memory` 查看、`/memory edit project|user` 用编辑器改。大项目的子目录可以有自己的 HENG.md（如 `frontend/HENG.md`），
  模型第一次读写那个目录的文件时自动附上，每份只附一次。
- **内置命令**：`/commit [要求]` 按仓库风格写提交信息并提交（不 push、不改历史）；`/review [关注点]` 审查没提交的改动，
  按严重程度列问题。在 `.heng-agent/commands/` 放同名的 `commit.md` / `review.md` 就能按自己团队的规矩改写。
- **`/doctor`**：检查配置、服务商连接（会真的连一次）、密钥、代理、终端、git、记忆、钩子、MCP、会话目录。
  `/doctor copy` 把检查结果连同最近的日志复制下来（用户目录换成 ~），反馈问题时直接贴。
- **查看状态**：`/status` 一屏看全版本、模型、会话、权限、MCP、说明文件；`/usage`（`/cost`）本会话的用量与花费、
  缓存命中率；`/stats` 今天 / 近 7 天 / 近 30 天的统计，按项目、按模型排名；`/context` 上下文被什么占着；
  `/hooks` 生效的钩子。
- **后台任务**：开发服务器、watch 这类不会自己结束的命令，模型会用 `run_in_background` 放到后台跑，之后用 `bash_output`
  看新输出、`kill_task` 停掉。前台命令跑着时按 **Ctrl+B** 也能把它转到后台（进程不停、已有输出不丢）。
  `/tasks` 查看、`/tasks kill bg1` 停止；状态栏会显示「后台 N」；退出 heng-agent（含 `-p` 结束）时停掉全部后台任务。
- **思考模式**：`/think` 切换（`/think on|off`、`/think 16000` 设预算、`/think show` 看最近一次思考），也可在配置
  `settings.thinking` / `settings.thinking_budget` 里常开。思考过程不刷屏：等待动画里显示想了多少字，结束后折叠成一行。
  Anthropic 协议下思考块（带签名）原样存进历史、调工具后原样传回（服务要求）；OpenAI 协议（DeepSeek 推理模型等）
  是否思考由模型决定，`reasoning_content` 只显示、不进历史（传回去会报错）。
- **思考强度**：`/effort` 选（或 `/effort high`、`/effort auto` 回到服务默认），也可写 `settings.effort`；状态栏显示 `✻ high`。
  请求怎么写按模型自动适配：Claude 4.6 以后用自适应思考加 `effort`（low / medium / high / xhigh / max）；
  Opus 5.5、Sonnet 5.5、Fable 的思考关不掉，`/think off` 时按 low 强度少想；更早的 Claude 与 DeepSeek、Kimi、GLM 等
  仍用思考预算，强度换算成预算（low 2k … max 64k）；OpenAI 协议发 `reasoning_effort`（只有 low / medium / high）。
- **自定义子智能体角色**：在 `.heng-agent/agents/名字.md`（项目）或 `~/.heng-agent/agents/`（用户）定义「测试员」「审查员」
  这类角色——开头写 `description`（模型据此挑）与 `tools`（不写就是只读），正文是它的提示词。模型用 `task` 工具派它们。
  只读角色不用确认、可以并行；带 `write_file` / `edit_file` / `bash` 的角色按你的权限模式确认、不并行，改的文件能 `/undo`。
  `/agents` 查看，`/agents new 名字` 建模板并打开编辑器，存好马上生效。
- **git 工作树隔离**：想试个有风险的改动、或让两件事互不干扰时，`heng-agent -w 名字` 启动，或会话里 `/worktree new 名字`，
  就在 `.heng-agent/worktrees/名字`（分支 `heng/名字`）里干活，不碰主分支和你没提交的改动（这个目录自动被 git 忽略）。
  `/worktree` 列出、`/worktree switch 名字|main` 切换、`/worktree remove 名字` 删除（分支没合并就保留）。
  改完在工作树里 `/commit`，回主目录 `git merge heng/名字`——合并可能冲突，不自动做。

## 内置技能

装好就有、不用配置的技能，模型在任务对得上时自动读它的完整说明再动手（`/skills` 查看）：

| 技能 | 什么时候用 |
|---|---|
| debugging | 报错、测试失败、行为不对：先复现、再定位、找到根因再修，最后加回归测试 |
| writing-tests | 写测试：照项目已有的框架与风格，覆盖正常路径、边界与出错情况 |
| refactoring | 重构：先有测试兜底，小步改、每步都验证，行为不变 |
| codebase-tour | 读懂陌生项目：怎么跑起来、模块怎么分工、关键流程怎么走 |
| security-check | 安全检查：密钥泄露、注入、越权、不安全的输入与依赖，按严重程度报告 |

想按自己团队的习惯改写，在 `.heng-agent/skills/<同名>/SKILL.md`（项目）或 `~/.heng-agent/skills/`（用户）放一个同名技能即可替换。

## 兼容 Claude Code 与 AGENTS.md

从别的编码工具转过来，项目里现成的配置直接能用，不用迁移：

| 配置 | 读哪里 | 说明 |
|---|---|---|
| 项目说明 | 根目录的 `HENG.md`、`AGENTS.md`、`CLAUDE.md`、`CLAUDE.local.md`；子目录里的同名文件 | 都读；内容一样的（如 CLAUDE.md 链到 AGENTS.md）只算一份；CLAUDE.md 的 `@路径` 引用会展开 |
| 用户说明 | `~/.heng-agent/HENG.md`、`~/.claude/CLAUDE.md` | |
| 技能 | `.claude/skills/`、`~/.claude/skills/` | 格式一样；同名时 `.heng-agent/` 的优先 |
| 子智能体 | `.claude/agents/`、`~/.claude/agents/` | Claude 的工具名（Read、Bash……）自动对应；不写 tools 时照 Claude 的规则继承全部工具 |
| MCP | 项目根目录的 `.mcp.json` | 支持 `${变量}`、`${变量:-默认值}`；项目里的服务照样要确认信任才启动 |
| 自定义命令 | `.claude/commands/`（可分子目录）、`~/.claude/commands/` | 支持 `$ARGUMENTS`、`$1`…`$9`、`argument-hint`、``!`命令` ``（先跑命令把输出拼进去：用户级的直接跑，项目里的先问你，脚本模式只在 auto 时跑） |
| 权限规则 | `~/.claude/settings.json`；项目 `.claude/settings.json`、`settings.local.json` | 规则自动翻译（`Bash(npm test:*)` → `bash(npm test*)` 等）；项目里的只采用拒绝规则；它的 `defaultMode` 不跟，权限模式由 heng-agent 自己定 |
| 钩子 | 同上几个 `settings.json` 的 `hooks` | 支持 PreToolUse、PostToolUse、UserPromptSubmit、Stop、SessionStart：照 Claude 的约定从标准输入传 JSON（工具名报 `Bash`、`Edit`……，文件参数是绝对路径的 `file_path`），设 `CLAUDE_PROJECT_DIR`，认退出码 2 与标准输出的 JSON 决定（`decision: block`、`permissionDecision: deny`、`additionalContext`）；项目里的要确认信任 |

拒绝规则对组合命令逐段检查（`cd x && 危险命令` 也拦得住），文件路径换写法（`./.env`、`E:\项目\.env`）也拦得住。

欢迎页会显示「兼容加载：……」，`/doctor` 也列出来。

几份说明并存时：系统提示词里按优先级从低到高排列——用户级在前、项目级在后，同一级里
`CLAUDE.md` < `AGENTS.md` < `CLAUDE.local.md` < `HENG.md`，并明确告诉模型「内容冲突时以后面的为准」；子目录的说明比根目录的更具体。
读到了写给 Claude Code 的说明时，还会附一段工具名对照（Bash → bash、Edit → edit_file……）。`/memory` 按这个顺序列出每份说明
各占多少 token、`#` 快速记忆写进哪个文件，合计超过 1 万 token 时提醒精简（如 CLAUDE.md 里只写一行 `@AGENTS.md`）。

`/init` 默认生成 `AGENTS.md`（跨工具的开放标准，别的工具也读得到），
项目里已有说明文件就更新现有的。不想读 Claude Code 的用户级配置（`~/.claude` 里的），在配置里设
`settings.claude_user_config` 为 `false`；项目里的照读。

有些 Claude 钩子是专给 Claude Code 自己用的集成（如智码的会话记录器），在 heng-agent 里跑会出错或记错，
用 `settings.claude_hooks_skip` 跳过：命令里含其中任一段文字的 Claude 钩子不跑，如 `["aicoder-claude-session-recorder"]`。

## 开发版与正式版

开发 heng-agent 的同时自己也在用它，两边互不干扰：

| | 正式版 | 开发版 |
|---|---|---|
| 命令 | `heng-agent` | `heng-dev`（`scripts/install_dev_command.py` 装一次；或直接跑仓库里的 `.venv/Scripts/heng-agent`） |
| 代码 | 从打了标签的版本装进环境，装好就不变 | 直接跑仓库源码，改完立即生效 |
| 数据 | `~/.heng-agent` | `~/.heng-agent-dev`（第一次运行从正式版复制一份配置，之后各改各的） |
| 标记 | — | 欢迎页品红边框、品红字标与「开发版」徽标，窗口标题带「[开发版]」，版本号带 git 位置 |

是不是开发版看代码在哪儿就知道（仓库的 `src/` 下就是开发版），也可以用环境变量 `HENG_AGENT_CHANNEL=dev|release` 强制；
`HENG_AGENT_HOME` 或 `--home` 可以直接指定数据目录。配置里有当前版本不认识的设置（新版写的）时只提示、不拦启动。

发布：改 `pyproject.toml` 与 `src/heng_agent/__init__.py` 里的版本号 → 在 CHANGELOG.md 记下改动 → 提交、打标签 `v版本号` →
从标签构建安装包装成正式版（见 CHANGELOG.md 开头的「发布步骤」）。

## 在编辑器里用（ACP）

`heng-agent --acp` 以 [Agent Client Protocol](https://agentclientprotocol.com)（ACP）运行：编辑器或桌面应用通过标准输入输出
驱动它，在自己的界面里聊天——流式显示回答、思考与工具调用，改文件、跑命令前在编辑器里弹窗确认（改文件时能直接看到改动对比），
随时取消，也能列出、恢复以前的会话。支持 ACP 的客户端都能用，比如 Zed：

```json
{
  "agent_servers": {
    "heng-agent": { "command": "heng-agent", "args": ["--acp"] }
  }
}
```

其他支持 ACP 的客户端（JetBrains 系列 IDE 等）按各自的说明添加命令 `heng-agent --acp` 即可。

- 服务商与密钥用 heng-agent 自己的配置（先在终端里运行一次 `heng-agent` 按引导配好），或者由客户端启动时用环境变量给（见下）；
- 客户端里有三个下拉框：模型（列出配好、能用的服务商）、权限模式（手动确认 / 自动改文件 / 计划模式 / 全部放行）、思考（开 / 关）；
- 项目里还没被信任的钩子与 MCP 服务在 ACP 模式下不加载（没法弹信任确认）：在终端里打开一次这个项目、确认信任即可。

### 启动时用环境变量给服务商

别的程序（如智码）启动 heng-agent 时，可以用环境变量直接给服务商——只在这次运行里用，不写进配置文件，
也不会弹第一次用的引导；终端模式、`-p` 与 `--acp` 都认：

| 环境变量 | 说明 |
|---|---|
| `HENG_AGENT_BASE_URL` | 服务地址。设了它才启用，设了就是这次运行的默认服务商（名字叫 `env`） |
| `HENG_AGENT_API_KEY` | 密钥 |
| `HENG_AGENT_MODEL` | 模型名（必填） |
| `HENG_AGENT_PROTOCOL` | `anthropic`（默认）或 `openai` |
| `HENG_AGENT_AUTH` | `auto`（默认）、`x-api-key` 或 `bearer` |

命令行的 `--provider` 仍然优先。用专门的变量名、不读 `ANTHROPIC_BASE_URL` 这类：不少人为别的工具全局设着
`ANTHROPIC_API_KEY`，一看到就用会悄悄绕开你在 heng-agent 里配好的默认服务商。

## 脚本模式（-p）

```bash
heng-agent -p "把 cart.py 的运费改成 15 元" --allowed-tools "edit_file,bash(python -m pytest*)"
cat error.log | heng-agent -p "分析这段错误"           # 管道内容附在问题后面
echo "解释一下 README" | heng-agent -p                 # 只写 -p：管道内容就是问题
heng-agent -p "统计代码行数" --output-format json        # 结束时输出一个 JSON：result、session_id、usage……
heng-agent -p "跑测试" --output-format stream-json      # 每个事件一行 JSON，给别的程序实时展示进度
```

`-p` 没人可问，需要确认的操作默认都拒绝：用 `--allowed-tools` 放行（规则写法同 `/permissions`，逗号分隔），
`--disallowed-tools` 额外禁止；或用 `--permission-mode accept-edits` / `auto`。

- **回答过程中输入框一直在**：可以接着打字，Enter 把这句话排进队列（灰色列在输入框上方）——普通的话在这批工具跑完时
  插进这一问，模型下一步就能看到；命令等这一问结束再执行（`/status`、`/usage`、`/tasks`、`/effort`、`/think` 这类马上执行）。
  光标在第一行时按 **↑** 把排着队的话全部取回来改。
- **`/btw 问题`**：旁支问题——随口问一句（回答中、平时都行），不打断正在进行的回答。它看得到到目前为止的对话，
  但不调工具、不进对话历史，答案显示在一个框里；之前问过的旁支问题会一起带上。
- **下一句建议**：每一问答完后，空的输入框里会用灰字给出一句你可能接着要说的话（比如回答最后问「要不要先做第一条」，
  建议就是「好，先做第一条吧」），按 **Tab** 或 **→** 填进输入框，可以改了再 Enter 发；直接打字就消失。
  没有明显的下一步时不给；计划模式里不给。每一问会多一次模型请求：主对话上一次请求读写过缓存时
  （不管哪种协议，以实际用量为准），请求和主对话的前缀完全一样，几乎全部读缓存（实测 DeepSeek：读缓存 1.5 万、
  新算不到 200 token）；服务不缓存时只带最近 3 问压成的几千字，不随对话变长而变贵。每次用量记在日志里。
  不想要就在配置的 `settings` 里写 `"prompt_suggestions": false`（或 `/config set settings.prompt_suggestions false`）。
- 回答中按 **ESC**（或 Ctrl+C）中断这一问：等模型时立刻断开（不会被当成网络抖动去重试），跑命令时连同子进程一起停掉；
  框里没发的草稿留着，排着队的话接着发；不退出程序。确认框里用 ↑↓ / y / a / n 选，**ESC 等于拒绝**
  （中文输入法开着时字母会被输入法截走，用 ↑↓ 加 Enter）。
- **ESC**：输入框里有字时**双击**清空；空输入框里**双击 ESC**（或 `/rewind`）选一问，对话与它改过的文件一起回到它之前，
  那一问的原话放回输入框，改了重发。**Ctrl+C**：第一次清空输入框，空输入框里连按两次退出。清掉的草稿存进了历史，
  按 ↑ 能找回。Ctrl+L 清屏。
- 要改文件时会显示红绿对比，回答 `y` 这次允许、`a` 本会话一直允许、`n` 拒绝。
- 斜杠命令：`/help` `/clear`（新会话）`/mode`（权限模式）`/provider`（服务商）`/model` `/compact`（压缩历史）
  `/undo`（撤销上一问）`/todo`（任务清单）`/cost`（累计用量与金额）`/exit`。
- **`@路径`**：输入里写 `@src/app.py`，文件内容直接附上。**`!命令`**：自己直接跑命令（不经过模型），
  输出会附在你下一句话里告诉模型。
- **撤销**：`/undo` 把上一问用 write_file / edit_file 改过的文件恢复原样（新建的删掉），对话也退回去。
  **bash 命令造成的改动（删文件、git 操作、构建产物）无法撤销**。
- **花费**：在配置档里填 `price_in` / `price_out`（每百万 token 的价格，按服务商控制台填）和 `currency`，
  `/cost` 就按金额显示。预设不带价格：各家常调价，写死容易显示错的数。
  命中缓存的部分另算：`price_cache_read` / `price_cache_write`（每百万 token），不填按输入价的 0.1 倍 / 1.25 倍
  （Anthropic 的定价）。走 OpenAI 协议的服务商（DeepSeek、通义、Kimi、OpenAI）大多也自动缓存，但折扣各不相同、
  写入一般不另收钱，按控制台填上 `price_cache_read`、`price_cache_write` 填 0，金额才准。
- **读网页**（`web_fetch` 工具）：除 `auto` 模式外都会先问你，网址完整显示——模型可能把代码内容拼进网址带出去。
- 回复按 Markdown 渲染（代码块、列表、表格），边生成边成形。
- **自动重试**：限流（429）、过载（529）、服务端错误、网络中断时自动重试，最多 4 次，界面上会提示。
- **自动压缩**：对话快撑满模型上下文（超过 80%）时，把旧历史总结成摘要继续干。上下文长度在配置档里用
  `context_window` 设；不写就自动定：先向服务商查（Anthropic 官方的模型接口、OpenRouter 的模型列表；中转站一般查不到），
  查不到按模型名推断（Claude、DeepSeek、Kimi、GLM、通义、OpenAI、Gemini、MiniMax 的常见型号，数字取自各家官方文档），
  都不认识用 128K（ollama 预设 32K）。
  `/status` 里写着长度是从哪来的；推断错了用 `/config set profiles.<服务商>.context_window 数字` 改，马上生效。

## 多开与配置隔离

可以同时开多个 heng-agent，互不干扰：

- **各实例独立**：`--provider`、`/provider`、`/mode`、「本会话一直允许」都只在各自进程的内存里；配置文件只读不写。
- **会话不会互相覆盖**：会话 id 带随机后缀，同一目录同一秒开两个也各写各的。
  `heng-agent --sessions` 列出这个目录的全部会话，`--resume` 接最近的，`--resume <id 或前缀>` 接指定的。
- **同一个文件别让两个实例同时改**：后写的会覆盖先写的（Claude Code 也一样）。多开时让它们处理不同的文件或目录。

配置分三层，后面的覆盖前面的：

| 层 | 位置 | 用途 |
|---|---|---|
| 内置预设 | 程序自带 | deepseek、kimi、glm… |
| 用户配置 | `~/.heng-agent/config.json` | 你的中转站、密钥、默认服务商 |
| 项目配置 | `项目根目录/.heng-agent/config.json` | 这个项目默认用哪个服务商、哪个模型 |

项目配置例子（项目 A 默认用 DeepSeek 的便宜模型，密钥仍在用户配置或环境变量里）：

```json
{"default": "ds-fast", "profiles": {"ds-fast": {"preset": "deepseek", "model": "deepseek-flash"}}}
```

`preset` 也能引用用户配置里定义的配置档（比如带密钥的中转站），项目里只写要改的字段。
**项目配置里不许写 `api_key`**：项目目录可能被提交进仓库，写了会直接报错。

**完全独立的一套配置**（不同账号、不同客户）：用环境变量 `HENG_AGENT_HOME` 或 `--home` 指到另一个目录，
配置、会话、输入历史都分开：

```bash
HENG_AGENT_HOME=~/.heng-agent-客户A heng-agent
```

## 技能、自定义命令、钩子

**技能**：某类任务的做法说明，模型用得上时自己去读。放在 `.heng-agent/skills/<名字>/SKILL.md`（项目）
或 `~/.heng-agent/skills/<名字>/SKILL.md`（所有项目通用），同名时项目的优先：

```markdown
---
name: test-style
description: 本项目写单元测试的规矩（新增或修改测试前必读）
---
- 每个测试方法第一行写中文 docstring，说明测的是什么
- 边界值至少测「刚好等于」和「差一点」
```

系统提示词里只列名字和 description，模型觉得对得上才读全文，所以装再多也不挤占上下文。技能目录里可以放模板、
清单等其他文件，模型按需读。`/skills` 查看已有技能。

**自定义命令**：把常用提示词存成 `.heng-agent/commands/<名字>.md`（或 `~/.heng-agent/commands/`），输入 `/名字 参数`
就展开发给模型。正文里的 `$ARGUMENTS` 换成参数，没写就把参数接在末尾。`-p "/名字 参数"` 同样可用。
内置命令（`/help`、`/undo`……）优先，同名的自定义命令不生效。

**钩子**：工具执行前后自动跑的命令，写在 `config.json`：

```json
{
  "hooks": {
    "pre_tool":  [{"match": "bash", "command": "python scripts/check_cmd.py"}],
    "post_tool": [{"match": "edit_file|write_file", "command": "ruff format \"$HENG_FILE\""}]
  }
}
```

- `match` 按工具名正则匹配；环境变量 `HENG_TOOL`、`HENG_TOOL_INPUT`（参数 JSON）、`HENG_FILE`（改的是哪个文件）。
- `pre_tool` 退出码 **2** 拦下这次调用，输出作为原因告诉模型；`post_tool` 的输出附在结果后面给模型
  （格式化改了什么、检查报了什么错）。
- 另有三个不针对工具的事件（`match` 可省，环境变量 `HENG_PROMPT` 是用户这句话 / 模型最后的回复）：
  - `user_prompt_submit`：消息发给模型前跑。输出作为补充上下文附在消息后面（如当前分支、最近的报错）；
    退出码 **2** 拦下这条消息不发（如防止把密钥发出去）。
  - `stop`：模型准备停下时跑。退出码 **2** 要求模型继续，输出交给模型（如「测试还没过，接着修」），最多连续 3 次。
  - `session_start`：启动时跑，输出附进系统提示词（如注入项目当前状态）。
- **项目里的钩子要你确认信任才会运行**：克隆来的仓库可能带着恶意钩子。交互模式第一次遇到会把命令完整列出来问你；
  钩子内容一改就要重新确认；`-p` 模式下没信任过的项目钩子直接跳过。用户目录里的钩子是你自己写的，直接生效。

## 子智能体、图片、MCP

**子智能体**（`task` 工具）：模型可以把调研 / 探索类的事交给子智能体去做（在大项目里找相关代码、梳理调用关系……），
子智能体独立搜索阅读，只把结论带回来，主对话不会被中间过程挤满。同一轮发出多个会**并行执行**（最多 4 个）。
子智能体**只读**（读文件、找文件、搜内容），不能改文件、跑命令，也不能再派子智能体；要改代码由主智能体来做。

- **后台子智能体**：模型可以把不急着用结论的调研放到后台（`run_in_background`），派出去马上接着干别的。
  它做完时：主智能体正在回答，就在这批工具跑完时把结论插进去；空闲，就自动发起一问把结论交给它
  （显示成一行「◆ 后台子智能体 #1「…」做完了」，框里敲了一半的字留着）。主对话按 ESC 不会把后台的停掉。
- **子智能体面板**：有子智能体在跑时，状态栏下面列出 `● main` 和每个子智能体（任务、用时、token、是否后台）。
  在输入框最后一行按 **↓** 选中，**Enter** 看它到现在为止读了哪些、搜了什么、写了什么，**ESC** 返回输入框。

**图片**：输入里 `@截图.png` 就把图片附上（png / jpg / gif / webp，单张 ≤ 5 MB）。**能不能看图取决于模型**：
Claude、GPT 等支持；DeepSeek 等纯文本模型不支持。

**MCP**：接入外部工具服务，在 `config.json` 里配置。两种连接方式：`command` 启动一个程序（stdio），
`url` 连一个已经在跑的服务（http，即 MCP 的 Streamable HTTP）：

```json
{
  "mcp_servers": {
    "sigil": {"command": "sigil-mcp", "args": ["--stdio"], "env": {"FOO": "bar"}, "timeout": 60},
    "ai-workstation": {"url": "https://ai-workstation-mcp.agilefr.com/mcp", "headers": {"Authorization": "Bearer 令牌"}}
  }
}
```

- 也认 `mcpServers` 这个写法（Claude Code、Kimi 用的），它们的配置可以直接贴过来。老式 SSE 传输不支持。
- 启动时每个服务一行：`MCP server "aicoder" connected · 90 tools (stdio)`，连不上的红色显示原因。
- **工具多时按需加载**：接几个大服务很容易上百个工具（实测 6 个常用服务 361 个、声明约 10 万 token），每次请求都带上
  会占掉一半上下文、每问都花这么多钱。所以 MCP 工具声明超过上下文的 10% 时，先不发声明，只给模型一个 `tool_search`：
  它按关键词搜，搜到的工具立即加载、下一步就能调用（实测每次请求从约 10 万 token 降到约 3 千）。
  配置 `settings.mcp_tool_search`：`auto`（默认）/ `on` / `off`。
- 工具注册成 `mcp__服务名__工具名`；`/mcp` 查看已接入的工具。
- 外部工具可能写数据库、发消息，**除 `auto` 模式外调用前都会问你**（`plan` 模式也一样）。
- **项目里配置的 MCP 服务要你确认信任才会启动**，和钩子一样：配置一改（包括换了 url）就要重新确认，`-p` 模式下没信任过的直接跳过。
- 启动失败的服务跳过并提示，不影响其他服务；退出时关掉 stdio 服务的进程、结束 http 服务的会话。

## 项目记忆

在项目根目录放一个 `HENG.md`，写上项目规矩（技术栈、命名约定、提交规范……），每次启动自动读入。
所有项目通用的写在 `~/.heng-agent/HENG.md`。

## 故障排查

先在 heng-agent 里运行 `/doctor`，一项项看是哪一环出了问题；要反馈问题就运行 `/doctor copy`，把复制下来的内容贴上。
运行日志在数据目录的 `logs/heng-agent.log`（正式版 `~/.heng-agent/logs/`，开发版 `~/.heng-agent-dev/logs/`）。

| 现象 | 原因与处理 |
|---|---|
| 敲 `heng-agent` 提示找不到命令 | 安装时改了 PATH，要**重开一个终端**才生效；还不行就运行 `uv tool update-shell` 再重开 |
| 一启动就报 `ModuleNotFoundError: heng_agent` | 多半是 Windows 上 heng-agent 开着时升级 / 重装：文件被占用，装到一半失败。关掉所有 heng-agent 窗口，重新运行一键安装命令 |
| `heng-agent upgrade` 说已是最新，但刚发了新版本 | uv 缓存了旧的版本列表（0.3.2 起升级时会刷新）。旧版本手动运行 `uv tool install --force --upgrade --refresh-package heng-agent heng-agent` |
| 连不上服务商 | 看 `/doctor` 的「服务商连接」与「代理」两行：地址、密钥、请求实际走的代理。要单独指定或不走代理，见上文「代理」 |
| 中转站报 401 | 配置档里试试改 `auth`：`bearer` 或 `x-api-key` |
| Shift+Enter 不能换行 | Windows Terminal 里运行 `/terminal-setup`；任何终端里 Ctrl+J、Alt+Enter 都能换行 |
| 配了 MCP 服务，有的连不上 | 欢迎页与 `/mcp` 会列出原因；改好后 `/mcp reconnect 服务名`，不用重启 |
| 出现「内部错误」 | 程序的 bug：这一问作废、会话照常。运行 `/doctor copy` 反馈给我们 |

## 开发

```bash
uv venv --python D:/software/dev/python/python.exe .venv
uv pip install --python .venv/Scripts/python.exe -e ".[dev]"
PYTHONIOENCODING=utf-8 .venv/Scripts/python.exe -m pytest -q
```

设计见 `docs/design/00-总体设计.md`，开发约定见 `CLAUDE.md`。
