这一课深入理解单一聊天原则、Hooks 确定性强制和 LSP 语义理解。
前言:为什么需要这三个概念?
在实际使用 Claude Code 时,你可能遇到过这些问题:
- 聊天越来越长,Claude 回答质量下降
- CLAUDE.md 里写了规则,但 Claude 有时不遵守
- 代码导航很慢,找个函数定义要等半天
这三个概念分别解决这些问题:
- 单一聊天原则 → 保持对话质量
- Hooks → 强制执行规则
- LSP → 提升代码理解速度
一、单一聊天原则:保持对话质量
1.1 核心问题
研究数据:
"当指令跨多轮传递时,平均性能下降 39%。"
"随着上下文窗口中 tokens 增加,模型准确回忆信息的能力下降。"
简单说:聊天越长,Claude 越"健忘"。
1.2 黄金法则
"一任务一聊天"(One Task, One Chat)
| 场景 | 正确做法 |
|---|---|
| 新功能开发 | 开新聊天 |
| Bug 修复(无关) | /clear 然后新任务 |
| 研究 vs 实现 | 分开聊天 |
| 20+ 轮对话 | 重新开始 |
1.3 /clear 命令
用法:
/clear
效果:
- 清空当前对话上下文
- 保留 CLAUDE.md 等配置
- 重新开始"干净"的对话
Anthropic 官方建议:
"经常在不同任务之间使用
/clear来重置上下文窗口。"
1.4 实战案例
❌ 错误示例
你:帮我实现登录功能
Claude:(实现登录)
你:现在帮我做个用户管理页面
Claude:(实现用户管理)
你:再帮我优化数据库查询
Claude:(开始混乱,可能忘记之前的上下文)
✅ 正确示例
# 聊天 1:登录功能
你:帮我实现登录功能
Claude:(实现登录)
你:测试通过,完成
# 聊天 2:用户管理
/clear
你:帮我做个用户管理页面
Claude:(全新上下文,专注用户管理)
# 聊天 3:数据库优化
/clear
你:帮我优化数据库查询
Claude:(全新上下文,专注优化)
1.5 何时需要 /clear?
信号:
- 对话超过 20 轮
- Claude 开始"忘记"之前说的
- 切换到完全不同的任务
- 感觉回答质量下降
经验法则:
"宁可多 /clear,不要让对话拖太长"
1.6 OpenClaw 中的对应概念
OpenClaw 也有类似的"会话管理"概念:
bash
# 查看当前会话
openclaw sessions list
# 清空会话(类似 /clear)
# 在对话中直接说:
你:"清空当前会话"
OpenClaw:*清空上下文* → 重新开始
" /reset 清空上下文"
OpenClaw 特有功能:
- Isolated Sessions:每个任务独立会话
- Session Timeout:自动清理长时间未用的会话
二、Hooks:确定性强制执行
2.1 核心问题
CLAUDE.md 的局限:
- CLAUDE.md 里的规则是"建议"
- Claude 在上下文压力下可能忽略
- 无法 100% 保证执行
示例:
markdown
# CLAUDE.md
## 绝对不要做
- 永不提交 .env 到 git
问题:Claude 可能在某些情况下"忘记"这条规则。
2.2 Hooks 是什么?
定义 :Hooks 是确定性的脚本,在特定时机自动执行。
关键区别:
| 机制 | 类型 | 可靠性 |
|---|---|---|
| CLAUDE.md 规则 | 建议 | 可以被覆盖 |
| Hooks | 强制 | 始终执行 |
2.3 Hook 事件类型
| 事件 | 触发时机 | 典型用途 |
|---|---|---|
| PreToolUse | 工具执行前 | 阻止危险操作 |
| PostToolUse | 工具完成后 | 运行 linters、格式化 |
| Stop | Claude 完成回合 | 质量门禁、自动测试 |
2.4 实战案例:阻止 Secrets 访问
配置 Hook
编辑 ~/.claude/settings.json:
json
{
"hooks": {
"PreToolUse": [
{
"matcher": "Read|Edit|Write",
"hooks": [{
"type": "command",
"command": "python3 ~/.claude/hooks/block-secrets.py"
}]
}
]
}
}
Hook 脚本
创建 ~/.claude/hooks/block-secrets.py:
python
#!/usr/bin/env python3
import json, sys
from pathlib import Path
# 敏感文件列表
SENSITIVE = {'.env', '.env.local', 'secrets.json', 'id_rsa'}
# 读取工具调用参数
data = json.load(sys.stdin)
file_path = data.get('tool_input', {}).get('file_path', '')
# 检查是否是敏感文件
if Path(file_path).name in SENSITIVE:
print(f"BLOCKED: Access to {file_path} denied.", file=sys.stderr)
sys.exit(2) # 退出码 2 = 阻止操作
sys.exit(0) # 退出码 0 = 允许操作
效果
你:帮我读取 .env 文件
Claude:*尝试调用 Read 工具*
Hook:*拦截* → BLOCKED: Access to .env denied.
Claude:抱歉,我无法访问 .env 文件(敏感文件被保护)
2.5 Hook 退出码
| 退出码 | 含义 | Claude 行为 |
|---|---|---|
| 0 | 允许操作 | 继续执行工具 |
| 1 | 错误 | 显示错误给用户 |
| 2 | 阻止操作 | 告诉 Claude 原因,让它换方案 |
2.6 更多 Hook 示例
自动格式化代码
json
{
"hooks": {
"PostToolUse": [
{
"matcher": "Write",
"hooks": [{
"type": "command",
"command": "prettier --write $FILE_PATH"
}]
}
]
}
}
自动运行测试
json
{
"hooks": {
"Stop": [
{
"hooks": [{
"type": "command",
"command": "npm test"
}]
}
]
}
}
2.7 OpenClaw 中的 Hooks
OpenClaw 也支持 Hooks,但实现方式略有不同:
配置位置 :~/.openclaw/openclaw.json
json
{
"hooks": {
"preToolUse": [
{
"tool": "exec",
"script": "~/.openclaw/hooks/check-command.sh"
}
],
"postToolUse": [
{
"tool": "write",
"script": "~/.openclaw/hooks/format-code.sh"
}
]
}
}
OpenClaw 特有功能:
- Webhook Hooks:任务完成后自动发送通知
- Cron Hooks:定时任务的 Hook
- Session Hooks:会话开始/结束时的 Hook
三、LSP:IDE 级代码智能
3.1 核心问题
传统方式:Claude 用 grep/ripgrep 搜索代码
- 慢(大型项目需要 45 秒)
- 不精确(只能文本匹配)
- 无法理解语义
示例:
你:找到 getUserById 函数的定义
Claude:*用 grep 搜索* → 找到 10 个匹配,不知道哪个是真的
3.2 LSP 是什么?
LSP(Language Server Protocol):
- 微软开发的标准协议
- 让编辑器/IDE 理解代码语义
- Claude Code v2.0.74+ 内置支持
效果:
- 900 倍更快(50ms vs 45 秒)
- 语义理解(知道函数调用关系)
- 实时诊断(类型错误、语法错误)
3.3 LSP 提供的能力
| 能力 | 功能 | 示例 |
|---|---|---|
| Go to Definition | 跳转到定义 | 点击函数名 → 跳到定义位置 |
| Find References | 查找所有引用 | 找到函数被调用的所有地方 |
| Hover | 悬停提示 | 鼠标悬停 → 显示类型签名 |
| Diagnostics | 实时诊断 | 代码错误实时标红 |
| Document Symbols | 文档符号 | 列出文件中所有函数/类 |
3.4 支持的语言
- Python
- TypeScript / JavaScript
- Go
- Rust
- Java
- C / C++
- C#
- PHP
- Kotlin
- Ruby
- HTML / CSS
3.5 实战对比
没有 LSP(传统方式)
你:找到 getUserById 函数的所有调用
Claude:*用 grep 搜索*
→ 找到 15 个匹配
→ 包括注释、字符串、其他同名函数
→ 耗时 45 秒
有 LSP
你:找到 getUserById 函数的所有调用
Claude:*用 LSP Find References*
→ 精确找到 3 个真实调用
→ 排除注释和字符串
→ 耗时 50ms
3.6 如何启用 LSP?
Claude Code v2.0.74+:
- 自动启用,无需配置
旧版本:
bash
export ENABLE_LSP_TOOL=1
3.7 LSP 实战案例
案例 1:重构函数名
你:把 getUserById 重命名为 fetchUserById
Claude:*用 LSP Find References*
→ 找到所有调用
→ 自动重命名所有引用
→ 保证不遗漏
案例 2:查找类型错误
你:检查代码中的类型错误
Claude:*用 LSP Diagnostics*
→ 实时检测类型不匹配
→ 列出所有错误位置
→ 给出修复建议
案例 3:理解代码结构
你:这个文件有哪些函数?
Claude:*用 LSP Document Symbols*
→ 列出所有函数、类、变量
→ 显示层级结构
→ 包含类型信息
3.8 OpenClaw 中的代码理解
OpenClaw 目前不支持 LSP,但有类似的代码理解能力:
readCode 工具:
bash
# OpenClaw 的代码理解
你:"分析 src/utils.ts 的结构"
OpenClaw:*用 readCode 工具*
→ AST 分析
→ 提取函数/类/变量
→ 理解依赖关系
对比:
| 特性 | Claude Code LSP | OpenClaw readCode |
|---|---|---|
| 速度 | 极快(50ms) | 较快(1-2s) |
| 精度 | 语义级 | AST 级 |
| 跨文件 | 支持 | 有限 |
| 实时诊断 | 支持 | 不支持 |
四、三者如何配合使用?
4.1 完整工作流
1. 单一聊天原则
↓
保持对话质量,避免上下文混乱
2. Hooks 强制执行
↓
确保安全规则 100% 生效
3. LSP 语义理解
↓
快速准确地理解代码
4.2 实战案例:重构项目
场景:重构一个大型项目的用户模块
步骤:
# 1. 开新聊天(单一聊天原则)
/clear
你:我要重构用户模块
# 2. Hooks 保护(确保不破坏测试)
Hook:PostToolUse → 自动运行测试
# 3. LSP 辅助(快速找到所有引用)
你:找到 User 类的所有使用
Claude:*用 LSP* → 精确列出 50 个引用
# 4. 执行重构
你:把 User 重命名为 UserModel
Claude:*用 LSP* → 自动重命名所有引用
Hook:*自动运行测试* → 确保没有破坏
# 5. 完成后清空
/clear
五、新手上路指南
第一周:养成 /clear 习惯
bash
# 每次切换任务前
/clear
# 对话超过 20 轮
/clear
# 感觉回答质量下降
/clear
第二周:配置基础 Hooks
bash
# 创建 Hook 目录
mkdir -p ~/.claude/hooks
# 配置阻止敏感文件访问
# 参考 2.4 节的示例
第三周:体验 LSP
bash
# 确保使用 v2.0.74+
claude --version
# 尝试语义导航
你:"找到 XXX 函数的所有调用"
六、常见问题
Q1: /clear 会丢失什么?
会丢失:
- 当前对话历史
- 临时上下文
不会丢失:
- CLAUDE.md 配置
- Skills
- MCP 连接
- Hooks 设置
Q2: Hooks 会影响性能吗?
轻微影响:
- PreToolUse:增加 10-50ms
- PostToolUse:取决于脚本复杂度
- Stop:通常可接受
建议:
- Hook 脚本保持简单
- 避免耗时操作
Q3: LSP 支持所有语言吗?
支持:
- 主流语言(见 3.4 节)
不支持:
- 小众语言
- 自定义 DSL
替代方案:
- 用 grep/ripgrep
- 用 AST 工具
Q4: OpenClaw 什么时候支持 LSP?
当前状态:
- 不支持原生 LSP
- 有 readCode 工具作为替代
未来计划:
- 可能在后续版本支持
总结
核心要点
-
单一聊天原则
- 一任务一聊天
- 频繁使用 /clear
- 避免上下文混乱
-
Hooks 确定性强制
- CLAUDE.md = 建议
- Hooks = 强制
- 100% 执行规则
-
LSP 语义理解
- 900 倍更快
- 语义级理解
- 实时诊断
三者关系
单一聊天 → 保持质量
↓
Hooks → 强制规则
↓
LSP → 提升速度
附录:快速参考
单一聊天
bash
/clear # 清空上下文
Hooks 配置
json
{
"hooks": {
"PreToolUse": [...],
"PostToolUse": [...],
"Stop": [...]
}
}
LSP 命令
找到 XXX 的定义
找到 XXX 的所有引用
检查类型错误
列出文件中的所有函数