mirror of
https://github.com/shareAI-lab/analysis_claude_code.git
synced 2026-02-04 13:16:37 +08:00
- Remove all reverse-engineered Claude Code source code - Replace with 100% original educational content from mini-claude-code - Add clear disclaimer: independent project, not affiliated with Anthropic - 5 progressive agent implementations (v0-v4, ~1100 lines total) - Include agent-builder skill for teaching agent construction - Bilingual documentation (EN + ZH) This repository now focuses purely on teaching how modern AI agents work through original, from-scratch implementations. Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
215 lines
9.5 KiB
Markdown
215 lines
9.5 KiB
Markdown
# mini Claude Code v0:Bash is All You Need
|
||
|
||
当我们完成 v1、v2、v3 三个版本后,一个问题浮出水面:**Agent 的本质到底是什么?**
|
||
|
||
v1 用 400 行代码证明了"模型即代理";v2 加入 Todo 实现结构化规划;v3 引入 Task 工具支持子代理。功能越来越强大,但代码也越来越多。能不能反过来走——**用最少的代码,保留最核心的能力?**
|
||
|
||
答案是 v0:**20 行核心代码,1 个 bash 工具,却拥有完整的 Agent 能力——包括子代理。**
|
||
|
||
本次完整教学代码地址:
|
||
https://github.com/shareAI-lab/mini_claude_code
|
||
|
||
## 1. 核心洞察:Bash 是meta接口、万能工具箱
|
||
|
||
Unix 哲学告诉我们:一切皆文件,一切皆可管道。而 bash 是这个哲学的入口:
|
||
|
||
| 你需要 | bash 命令 |
|
||
|--------|-----------|
|
||
| 读文件 | `cat`, `head`, `tail`, `grep` `...` |
|
||
| 写文件 | `echo '...' > file`, `sed -i`, `...` |
|
||
| 搜索 | `find`, `grep`, `rg` |
|
||
| 执行 | `python`, `npm`, `make` |
|
||
| **子代理** | `python v0_bash_agent.py "task"`|
|
||
|
||
最后一行是关键:**通过 bash 调用自身,就实现了子代理机制**。不需要 Task 工具,不需要 Agent Registry,不需要任何额外代码。
|
||
|
||
## 2. 完整版代码
|
||
|
||
```python
|
||
#!/usr/bin/env python
|
||
"""v0_bash_agent.py - 极简 Claude Code (20行核心) | Bash is All You Need"""
|
||
from anthropic import Anthropic
|
||
import subprocess, sys, os
|
||
|
||
client = Anthropic(api_key="your-api-key", base_url="https://api.moonshot.cn/anthropic")
|
||
TOOL = [{"name": "bash", "description": """Execute shell command. Common patterns:
|
||
- Read: cat/head/tail, grep/find/rg/ls, wc -l
|
||
- Write: echo 'content' > file, sed -i 's/old/new/g' file
|
||
- Subagent: python v0_bash_agent.py 'task description' (spawns isolated agent, returns summary)""",
|
||
"input_schema": {"type": "object", "properties": {"command": {"type": "string"}}, "required": ["command"]}}]
|
||
SYSTEM = f"""You are a CLI agent at {os.getcwd()}. Solve problems using bash commands.
|
||
|
||
Rules:
|
||
- Prefer tools over prose. Act first, explain briefly after.
|
||
- Read files: cat, grep, find, rg, ls, head, tail
|
||
- Write files: echo '...' > file, sed -i, or cat << 'EOF' > file
|
||
- Subagent: For complex subtasks, spawn a subagent to keep context clean:
|
||
python v0_bash_agent.py "explore src/ and summarize the architecture"
|
||
|
||
When to use subagent:
|
||
- Task requires reading many files (isolate the exploration)
|
||
- Task is independent and self-contained
|
||
- You want to avoid polluting current conversation with intermediate details
|
||
|
||
The subagent runs in isolation and returns only its final summary."""
|
||
|
||
def chat(prompt, history=[]):
|
||
history.append({"role": "user", "content": prompt})
|
||
while True:
|
||
r = client.messages.create(model="kimi-k2-turbo-preview", system=SYSTEM, messages=history, tools=TOOL, max_tokens=8000)
|
||
content = [{"type": b.type, **({"text": b.text} if hasattr(b, "text") else {"id": b.id, "name": b.name, "input": b.input})} for b in r.content]
|
||
history.append({"role": "assistant", "content": content})
|
||
if r.stop_reason != "tool_use":
|
||
return "".join(b.text for b in r.content if hasattr(b, "text"))
|
||
results = []
|
||
for b in [x for x in r.content if x.type == "tool_use"]:
|
||
print(f"\033[33m$ {b.input['command']}\033[0m")
|
||
try: out = subprocess.run(b.input["command"], shell=True, capture_output=True, text=True, timeout=300, cwd=os.getcwd())
|
||
except subprocess.TimeoutExpired: out = type('', (), {'stdout': '', 'stderr': '(timeout)'})()
|
||
print(out.stdout + out.stderr or "(empty)")
|
||
results.append({"type": "tool_result", "tool_use_id": b.id, "content": (out.stdout + out.stderr)[:50000]})
|
||
history.append({"role": "user", "content": results})
|
||
|
||
if __name__ == "__main__":
|
||
if len(sys.argv) > 1: print(chat(sys.argv[1])) # 子代理模式
|
||
else:
|
||
h = []
|
||
while (q := input("\033[36m>> \033[0m")) not in ("q", "exit", ""): print(chat(q, h)) # 交互模式
|
||
```
|
||
|
||
## 3. 子代理机制:递归的优雅
|
||
|
||
v3 用了 ~150 行代码实现子代理:Agent Registry、Task 工具、工具过滤、进度显示...
|
||
|
||
v0 只需要一行 bash 命令:
|
||
|
||
```bash
|
||
python v0_bash_agent.py "explore the codebase and summarize"
|
||
```
|
||
|
||
**为什么这能工作?**
|
||
|
||
1. **进程隔离** = 上下文隔离
|
||
- 子进程有独立的 `history=[]`
|
||
- 不会污染父进程的对话历史
|
||
|
||
2. **stdout** = 结果返回
|
||
- 子代理的 `print(chat(...))` 输出到 stdout
|
||
- 父代理通过 `subprocess` 捕获,作为工具结果
|
||
|
||
3. **递归调用** = 无限嵌套
|
||
- 子代理可以再调用子代理
|
||
- 天然支持任意深度的任务分解
|
||
|
||
```sh
|
||
主代理
|
||
└─ bash: python v0_bash_agent.py "分析架构"
|
||
└─ 子代理(独立进程,独立历史)
|
||
├─ bash: find . -name "*.py"
|
||
├─ bash: cat src/main.py
|
||
└─ 返回摘要 → stdout → 父代理收到结果
|
||
```
|
||
|
||
## 4. 与 v3 的对比
|
||
|
||
| 机制 | v3 (Task 工具) | v0 (Bash 递归) |
|
||
|------|----------------|----------------|
|
||
| 代码行数 | ~900 行 | ~50 行 |
|
||
| 子代理实现 | Task tool + Agent Registry | `python self 'task'` |
|
||
| 上下文隔离 | 独立 messages[] | 独立进程 |
|
||
| 工具过滤 | 白名单机制 | 无(bash 万能) |
|
||
| 进度显示 | SubagentProgress 类 | 直接 stdout |
|
||
| 灵活性 | 高(多种代理类型) | 中(统一行为) |
|
||
|
||
**v0 牺牲了什么?**
|
||
- 没有代理类型区分(explore/code/plan)
|
||
- 没有工具白名单(子代理也能写文件)
|
||
- 没有优雅的进度显示
|
||
|
||
**v0 得到了什么?**
|
||
- 极致简洁:20 行核心逻辑
|
||
- 零额外概念:不需要理解 Task、Agent Registry
|
||
- 完整能力:读、写、搜索、执行、子代理
|
||
|
||
## 5. 背后的思想
|
||
|
||
> **简单系统的涌现能力**
|
||
|
||
v0 证明了一个反直觉的事实:**复杂能力可以从简单规则中涌现**。
|
||
|
||
1. **一个工具足矣**
|
||
|
||
bash 是通往 Unix 世界的大门。通过它,模型可以调用任何命令、任何程序、任何脚本。不需要为每种能力单独实现工具。
|
||
|
||
2. **递归即层级**
|
||
|
||
程序调用自身是计算机科学最优雅的模式之一。v0 用同样的方式实现子代理:不是设计新机制,而是复用已有能力。
|
||
|
||
3. **进程即隔离**
|
||
|
||
操作系统早就解决了"如何隔离执行环境"的问题。v0 直接借用这个能力,而不是在应用层重新实现。
|
||
|
||
4. **约束在提示词**
|
||
|
||
v3 用代码实现工具过滤;v0 用提示词引导行为。前者是硬约束,后者是软约束。对于教学目的,软约束足够了。
|
||
|
||
## 6. 极限压缩版(16 行)
|
||
|
||
如果追求极致,还可以进一步压缩:
|
||
|
||
```python
|
||
#!/usr/bin/env python
|
||
"""v0_bash_agent_mini.py - 极限压缩版 (16 行)"""
|
||
from anthropic import Anthropic; import subprocess as sp, sys, os
|
||
C = Anthropic(api_key="your-key", base_url="https://api.moonshot.cn/anthropic")
|
||
T = [{"name":"bash","description":"Shell. Subagent: python v0_bash_agent_mini.py 'task'","input_schema":{"type":"object","properties":{"command":{"type":"string"}},"required":["command"]}}]
|
||
S = f"CLI agent at {os.getcwd()}. Use bash. Spawn subagent for complex tasks. Be concise."
|
||
|
||
def chat(p, h=[]):
|
||
h.append({"role":"user","content":p})
|
||
while (r:=C.messages.create(model="kimi-k2-turbo-preview",system=S,messages=h,tools=T,max_tokens=8000)).stop_reason=="tool_use":
|
||
h.append({"role":"assistant","content":[{"type":b.type,**({"text":b.text}if hasattr(b,"text")else{"id":b.id,"name":b.name,"input":b.input})}for b in r.content]})
|
||
h.append({"role":"user","content":[{"type":"tool_result","tool_use_id":b.id,"content":(print(f"\033[33m$ {b.input['command']}\033[0m"),o:=sp.run(b.input["command"],shell=1,capture_output=1,text=1,timeout=300),print(o.stdout+o.stderr or"(empty)"))and""or(o.stdout+o.stderr)[:50000]}for b in r.content if b.type=="tool_use"]})
|
||
h.append({"role":"assistant","content":[{"type":b.type,**({"text":b.text}if hasattr(b,"text")else{"id":b.id,"name":b.name,"input":b.input})}for b in r.content]})
|
||
return "".join(b.text for b in r.content if hasattr(b,"text"))
|
||
|
||
if __name__=="__main__":[print(chat(sys.argv[1]))]if len(sys.argv)>1 else[print(chat(q,h))for h in[[]]for _ in iter(int,1)if(q:=input("\033[36m>> \033[0m"))not in("q","")]
|
||
```
|
||
|
||
16 行,功能完全相同。纯属炫技,不推荐用于学习。
|
||
|
||
## 7. 系列总结
|
||
|
||
| 版本 | 行数 | 核心主题 | 关键洞察 |
|
||
|------|------|----------|----------|
|
||
| **v0** | ~50 | Bash is All You Need | 一个工具 + 递归 = 完整 Agent |
|
||
| v1 | ~400 | Model as Agent | 模型是主体,代码是工具循环 |
|
||
| v2 | ~650 | 结构化规划 | Todo 工具引导模型行为 |
|
||
| v3 | ~900 | 分而治之 | Task 工具实现专业化子代理 |
|
||
|
||
**从 v0 到 v3,代码在增加,但核心没变:**
|
||
|
||
```sh
|
||
while True:
|
||
response = model.call(messages, tools)
|
||
if response.stop_reason != "tool_use":
|
||
return response.text
|
||
results = execute_tools(response.tool_calls)
|
||
messages.append(results)
|
||
```
|
||
|
||
这就是 Agent 的全部本质——**一个让模型持续调用工具直到完成任务的循环**。
|
||
|
||
v0 用最少的代码证明了这一点。其他版本只是在这个框架上添加细则:Todo 让规划可见,Task 让分工成为可能,进度显示让过程可观测。但大的框架从未改变
|
||
|
||
|
||
👋 代码是思想在计算机世界的投影,Agent代码是【Agent模型与、真实计算机系统、间的“信号线”】
|
||
|
||
---
|
||
|
||
**Bash is All You Need.**
|
||
|
||
完整代码见仓库 `v0_bash_agent.py` 和 `v0_bash_agent_mini.py`。
|
||
|
||
|
||
如果你想要生产级实现,欢迎使用 [Kode Agent CLI](https://github.com/shareAI-lab/Kode) |