CrazyBoyM 85f44c358a Complete rewrite: original educational content only
- 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>
2025-12-31 07:01:42 +08:00

215 lines
9.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# mini Claude Code v0Bash 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)