ChCode: Python 7000 行代码手搓了一个终端 Coding Agent

7000 行代码手搓了一个终端 Coding Agent,支持视觉分析、Git 回滚、子代理并行

从一个 tkinter 小玩具到 14 个工具、9 层中间件管道的终端编程代理 --- ChCode 开发全记录

起因:一个 tkinter 小玩具

之前我写了一个叫 chat-agent 的 tkinter 桌面应用,用 LangChain 调 API 聊天。功能很基础,但用着用着我发现一个问题:

桌面 GUI 太重了,程序员真正需要的是终端里的 AI 助手。

于是我开始把它改成 CLI 工具,名字也从 chat-agent 变成了 ChCode --- chat-agent 遇上 code。

改着改着,功能越加越多:Git 检查点、子代理并行、视频分析、会话分叉...... 最终变成了一个 7000+ 行 Python 代码、14 个内置工具 的完整项目。

今天就把整个设计思路分享出来,希望能给你一些启发。


功能全景:这玩意能干啥?

先列一下 ChCode 的 12 大功能模块:

模块 亮点
模型管理 兼容所有 OpenAI 兼容 API,内置 ModelScope(2000次/天免费)、LongCat(5000万+ token/天免费)
视觉多模态 支持图片+视频分析,大图自动缩放,支持 PNG/JPG + MP4
会话持久化 SQLite 存储,LangGraph 检查点,跨会话保持
Git 集成 编辑消息自动回滚工作目录,任意消息创建分支
人工审核 Common(逐条审批)/ YOLO(全自动) Tab 一键切换
子代理系统 Explore(只读搜索)/ Plan(架构设计)/ General(全能力),支持并行
技能系统 项目级 + 全局技能目录,中间件注入 system prompt
终端 UI Rich 渲染,流式输出,状态栏显示上下文用量
跨平台 Windows 默认 Git Bash,回退 PowerShell;Linux/Mac 原生 bash
可观测性 LangSmith 追踪,429 限流自动禁用
上下文压缩 手动压缩或接近 token 上限时自动摘要,告别上下文溢出
环境隔离 每个项目独立 .chat/ 目录,互不干扰

核心架构:中间件管道

ChCode 用 LangChain 的中间件系统构建了一条 9 层处理管道,每次模型调用都会依次经过这些处理层:

  1. 工具错误兜底 --- 工具执行异常不会直接崩溃,而是返回错误信息让模型自行修正
  2. 视觉工具智能屏蔽 --- 如果当前模型本身支持多模态(如 Qwen-VL),自动屏蔽 vision 工具,改为直接把图片/视频嵌入消息
  3. 工具结果截断与预算控制 --- 过大的工具输出会被自动截断,同时控制每轮总 token 消耗
  4. 技能动态注入 --- 根据已安装的技能,动态拼装 system prompt,注入技能元数据
  5. 模型动态加载 --- 支持运行时切换模型,无需重建 agent
  6. 指数退避重试 + 备用模型切换 --- API 调用失败时按 3/10/30/60 秒间隔重试最多 4 次,全部失败后自动切换到备用模型
  7. 隐藏消息过滤 --- 压缩标记等内部消息在发送给模型前会被自动过滤
  8. 上下文裁剪 --- 当 token 数超过 10 万时,自动清理旧的工具调用结果(文件读取结果永不清理),保留最近 3 条
  9. 自动摘要 --- 当 token 数达到上下文窗口的 90% 时,用当前模型自动摘要历史对话,保留最近 20 条消息

最后还有一层 人工审核中间件(HITL),在 Common 模式下拦截高风险工具调用(bash、edit、write_file),等待用户确认后才执行。

这种分层设计的好处是:每一层只做一件事,新增功能只需要加一层中间件,不用动其他代码。


Git 检查点:编辑消息 = 回滚代码

这是 ChCode 最酷的功能之一。

当你通过 /messages 编辑历史消息时,ChCode 不只是修改聊天记录 ------ 它会用 Git 把工作目录回滚到那个时间点的状态

举个例子:

复制代码
你: 帮我写一个用户注册 API
AI: [写了一堆代码,创建了 5 个文件]
你: 帮我加个邮箱验证
AI: [又改了 3 个文件]

这时候你发现方向不对,用 /messages 回到第 1 条消息,编辑成:
你: 帮我写一个用户登录 API(用 JWT)

ChCode 自动:
1. git reset --hard 到第 1 条消息时的提交
2. 删除后面 4 条消息
3. 把你的新消息填入输入框

更狠的是 分叉功能(Fork) :你可以从任意消息创建一个新分支,带着那个时间点的代码状态,去探索另一条实现路径。就像 Git 的 checkout -b,但在聊天维度

原理很简单:每次 AI 完成一轮操作,ChCode 自动执行 git add . && git commit,把提交 ID 和消息 ID 绑定在一起。编辑/分叉时,根据消息 ID 找到对应的 Git 提交,精准回滚。


子代理系统:隔离上下文,并行执行

ChCode 内置 3 种子代理:

代理类型 用途 权限
Explore 代码库快速搜索 只读,禁止创建和修改文件
Plan 架构设计、方案规划 只读,禁止创建和修改文件
General 全能力编程 完整工具集

为什么要只读代理?

因为 Explore 和 Plan 只需要读代码。给它们写权限是危险的 ------ 一个搜索代理不应该顺手帮你改代码。ChCode 在 system prompt 里就明确禁止了文件创建和修改操作。

并行执行

你可以同时启动多个子代理处理独立任务。终端会显示实时进度条:

复制代码
  Explore: 搜索 API 路由定义... 120s 剩余 [████████░░░░░░░░]
  Plan: 分析数据库模型... 120s 剩余 [████████░░░░░░░░]

子代理运行在隔离上下文中,不会污染主对话。完成后只把最终报告返回给主代理。

自定义代理

你还可以在 .chat/agents/ 目录下定义自己的代理类型,配备专属工具和指令。


统一国产推理模型

国内推理模型(Qwen、DeepSeek、GLM)的 reasoning 输出字段各不相同:

模型 reasoning 字段名
Qwen reasoning_content
DeepSeek reasoning
GLM thought
通用 thinking
自定义 thought_process / reasoning_text / thought_content

ChCode 通过一个增强版的 ChatOpenAI 类,自动检测并统一这些字段 。上层代码只需要读 reasoning 就能拿到思考过程,不用关心底层是哪个模型。流式输出时也能正确累积 reasoning chunk。


终端 UI:不只是能用,还要好看

ChCode 用 Rich + prompt-toolkit 打造了一套完整的终端 UI 体验。

底部状态栏

实时显示当前模型、上下文用量、Git 检查点数、工作模式:

复制代码
────────────────────────────────────────────────────────────
Qwen/Qwen3-235B-A22B  45.2K/128K 35%  普通模式  Git (12 cp)  cwd: D:\Projects
魔搭今日免费额度剩余: 全局 1856/2000 │ 模型(Qwen3-235B) 98/100

流式输出

逐 token 渲染 AI 回复,推理模型的 thinking 过程用灰色斜体 Panel 展示:

复制代码
┌─ Thinking ──────────────────────────────────────────────┐
│ 用户需要一个用户注册 API,我应该先检查现有的项目结构...   │
│ 看到已经有 models/user.py,可以基于这个来扩展...         │
└─────────────────────────────────────────────────────────┘

好的,我来帮你写用户注册 API。先看一下现有的项目结构...

工具审批界面

Common 模式下,每次工具调用都会弹出来让你确认。编辑操作会显示左右对比 diff

复制代码
[HITL] edit  修改文件: src/api/user.py

 旧代码                           新代码
─────────────────────────────────────────────────────────
  1   def get_user(user_id: int):  1 + def create_user(username, email, pwd):
                                   2 +     """创建新用户"""
                                   3 +     hashed = hash_password(pwd)
                                   4 +     return db.create(username, email, hashed)

  批准 (y) / 拒绝 (n)

左边显示被替换的原始代码,右边红色 - 行对应旧内容,绿色 + 行对应新内容,一目了然。

命令自动补全

输入 / 自动弹出下拉列表,支持模糊搜索:

复制代码
 /new        新会话
 /history    历史会话
 /model      模型管理
 /messages   管理历史消息
 /compress   压缩会话
 /mode       切换模式
 /skill      技能管理

免费模型白嫖指南

ChCode 内置了多个免费平台的快捷配置,零成本上手

ModelScope(魔搭)

  • 每天 2000 次免费模型调用
  • 支持 Qwen3-235B-A22B-Thinking 等顶级模型
  • 状态栏实时显示剩余额度(全局 + 每模型)
  • 自动检测 ModelScopeToken 环境变量

LongCat

  • 每天最低 5000 万+ 免费 token
  • 适合大量代码生成场景

首次运行向导

首次启动时,ChCode 会自动扫描你的环境变量,支持一键配置:

复制代码
扫描到环境变量: ModelScopeToken
✓ 已自动配置 ModelScope 模型

还需要配置其他模型吗?
> OpenAI
> DeepSeek
> 跳过

跨平台 Shell 抽象

ChCode 做了一层 Shell 抽象,抹平了平台差异:

  • Windows:优先使用 Git Bash,不可用时回退到 PowerShell
  • Linux/Mac:使用系统 bash/zsh

所有 Shell 命令都在持久化会话中执行,cd 操作会自动同步到上层,确保工具的工作目录始终一致。


项目架构一览

复制代码
chcode/
├── cli.py                  # Typer CLI 入口 + LangSmith 429 防护
├── chat.py                 # REPL 主循环、斜杠命令、HITL 审批
├── agent_setup.py          # Agent 构建、中间件管道、模型重试与回退
├── config.py               # 模型配置、环境变量检测、首次运行向导
├── display.py              # Rich 渲染、流式输出、状态栏、子代理进度
├── prompts.py              # 交互式提示(select/confirm/text/checkbox)
├── session.py              # 会话管理器(SQLite + LangGraph)
├── skill_manager.py        # 技能安装/删除 UI
├── vision_config.py        # 视觉模型配置
├── agents/
│   ├── definitions.py      # 3 种内置代理定义(Explore/Plan/General)
│   ├── loader.py           # 从 .chat/agents/ 加载自定义代理
│   └── runner.py           # 子代理执行引擎
└── utils/
    ├── tools.py            # 14 个内置工具
    ├── shell/              # Shell 抽象层(Bash/PowerShell/CWD 追踪)
    ├── enhanced_chat_openai.py  # 统一国产推理模型
    ├── git_manager.py      # Git 检查点管理(commit/rollback/fork)
    ├── git_checker.py      # Git 可用性检测
    ├── skill_loader.py     # 技能发现与加载
    ├── modelscope_ratelimit.py  # ModelScope API 限额实时监控
    ├── tool_result_pipeline.py  # 工具输出截断与 token 预算
    ├── multimodal.py       # 多模态媒体处理(图片/视频编码)
    └── json_utils.py       # JSON 配置文件缓存读写

写在最后

ChCode 是我写过的最大的个人 Python 项目之一。从 tkinter 小玩具到 7000+ 行的终端工具,最大的感触是:

好的架构不是设计出来的,是重构出来的。

9 层中间件管道不是一开始就想好的,而是在不断加功能的过程中,发现"这个逻辑应该独立出来"、"这个可以做成中间件",逐步演化而成。

如果你也在做类似的 AI 工具,或者对终端编程代理感兴趣,欢迎来交流:


如果这篇文章对你有启发,点个赞再走吧,这对我真的很重要!

相关推荐
AI品信智慧数智人1 小时前
你的五一小长假,有AI伴游助手陪伴吗?
人工智能
dinl_vin1 小时前
LangChain 系列·(六):RAG 评估——你怎么知道它够好?
人工智能·langchain
玩转单片机与嵌入式1 小时前
别再只把 MCU 当控制器:新一代芯片正在把 AI 推理搬到设备端
人工智能·单片机·嵌入式硬件
kabuto_hui1 小时前
【大模型系列】DLLM与Block Diffusion的区别与联系
人工智能·大模型
羊羊小栈1 小时前
基于「YOLO目标检测 + 多模态AI分析」的宠物猫狗健康智能检测分析预警系统
人工智能·yolo·目标检测·计算机视觉·毕业设计·大作业
苏三的开发日记2 小时前
Embedding与向量数据库
人工智能
看月亮的方源2 小时前
Transformer原理讲解
人工智能
peterfei2 小时前
IfAI v0.4.6 发布:多线程并发对话 + Rust TUI 架构重构实战
人工智能·ai编程
疯狂成瘾者2 小时前
总价包干(Lump Sum / Fixed Price Contract)
人工智能