Claude Code 实战 (21):水晶包开发完整指南
导读: 这是 Claude Code 源码解析系列的第 21 篇,实战篇第 1 篇。基于前 20 篇的理论分析,实战开发 OpenClaw 水晶包。
📋 目录
水晶包是什么?
水晶包架构设计
实战:开发文件操作水晶包
水晶包验证流程
水晶包发布与共享
总结
水晶包是什么? 概念定义 水晶包 (Crystal Package) = Claude Code 技能 + OpenClaw 规范
1 2 3 4 水晶包 = 标准化能力 (脚本 + 配置) + 可复用设计 (任意 Agent 安装即用) + 完整验证 (测试 + 文档)
水晶包 vs Claude Code 技能
特性
Claude Code 技能
OpenClaw 水晶包
格式
SKILL.md + 脚本
CRYSTAL.md + 脚本
注册
技能注册表
水晶包注册中心
验证
基础测试
完整验证流程
分发
本地加载
水晶包市场
版本
无
语义化版本
水晶包结构 1 2 3 4 5 6 7 8 9 10 11 12 my-crystal/ ├── CRYSTAL.md # 水晶包定义 ├── package.json # 包信息 ├── scripts/ # 执行脚本 │ ├── main.sh │ └── helpers/ ├── config/ # 配置文件 │ └── default.yaml ├── tests/ # 测试用例 │ └── test.sh └── docs/ # 文档 └── README.md
水晶包架构设计 基于 Claude Code 的 20 个功能特性 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 水晶包能力 = Claude Code 功能特性 OpenClaw 化 1. Bash 命令执行 → 水晶包安全执行 2. 文件操作 → 水晶包文件管理 3. 文件搜索 → 水晶包快速定位 4. Agent 管理 → 水晶包 Agent 协作 5. 技能系统 → 水晶包技能注册 6. MCP 集成 → 水晶包 MCP 扩展 7. 任务管理 → 水晶包后台任务 8. Web 功能 → 水晶包网络能力 9. 权限系统 → 水晶包权限控制 10. 插件系统 → 水晶包插件机制 11. 会话管理 → 水晶包会话持久化 12. 上下文管理 → 水晶包上下文优化 13. 记忆系统 → 水晶包记忆存储 14. 配置管理 → 水晶包配置中心 15. 命令系统 → 水晶包命令注册 16. 启动优化 → 水晶包懒加载 17. 安全模型 → 水晶包安全检查 18. UI 系统 → 水晶包终端 UI 19. 日志遥测 → 水晶包日志记录 20. 状态管理 → 水晶包状态同步
水晶包分层架构 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 ┌─────────────────────────────────────────────────────────────┐ │ 水晶包应用层 │ │ (博客发布、数据分析、代码审查...) │ └─────────────────────┬───────────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────────────┐ │ 水晶包核心层 │ │ ├── 能力标准化 (基于 Claude Code 20 特性) │ │ ├── 接口规范化 (统一输入输出) │ │ └── 验证流程化 (完整测试验证) │ └─────────────┬───────────────────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────────────┐ │ OpenClaw 平台层 │ │ ├── Agent 运行时 │ │ ├── 工具系统 │ │ └── 配置中心 │ └─────────────────────────────────────────────────────────────┘
实战:开发文件操作水晶包 步骤 1:创建水晶包目录 1 2 3 mkdir -p ~/.openclaw/crystals/file-ops/{scripts,config,tests,docs}cd ~/.openclaw/crystals/file-ops
步骤 2:编写 CRYSTAL.md 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 --- name: file-ops version: 1.0.0 description: 文件操作水晶包 (基于 Claude Code FileEditTool) author: John license: MIT # 能力声明 (基于 Claude Code 功能特性) capabilities: - name: file_read description: 安全读取文件 based_ on: Claude Code FileReadTool features: - 流式读取 - 大文件优化 - 路径验证 - name: file_write description: 安全写入文件 based_on: Claude Code FileWriteTool features: - 原子写入 - 自动备份 - 目录自动创建 - name: file_edit description: 智能文件编辑 based_on: Claude Code FileEditTool features: - 差异显示 - 模糊匹配 - 多版本备份 # 依赖 dependencies: - name: diff version: ^5.1.0 # 配置 config: backup_dir: ~/.openclaw/backups max_versions: 5 allowed_dirs: - ~/.openclaw/workspace denied_dirs: - /etc - /root - /boot # 权限 permissions: - file_read - file_ write - bash (limited) --- # 文件操作水晶包 基于 Claude Code FileRead/Write/Edit Tool 实现的 OpenClaw 水晶包。 ## 使用方式 ### 读取文件 ```bash openclaw run file-ops read --path "./test.txt"
写入文件 1 openclaw run file-ops write --path "./test.txt" --content "Hello"
编辑文件 1 2 3 openclaw run file-ops edit \ --path "./test.txt" \ --changes '[{"oldText":"Hello","newText":"Hi"}]'
安全特性
路径验证 - 只允许访问指定目录
原子写入 - 防止文件损坏
多版本备份 - 可随时恢复
差异显示 - 修改前预览
测试
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 ### 步骤 3:实现核心脚本 **文件:** `scripts/file-read.sh` ```bash #!/bin/bash # 文件读取脚本 (基于 Claude Code FileReadTool) set -e # 参数解析 PATH="" LIMIT=1000 OFFSET=0 ENCODING="utf-8" while [[ $# -gt 0 ]]; do case $1 in --path) PATH="$2" shift 2 ;; --limit) LIMIT="$2" shift 2 ;; --offset) OFFSET="$2" shift 2 ;; --encoding) ENCODING="$2" shift 2 ;; *) echo "Unknown option: $1" exit 1 ;; esac done # 验证路径 validate_path() { local path="$1" local resolved=$(realpath "$path" 2>/dev/null || echo "$path") # 检查是否在允许目录 local allowed_dirs=("$HOME/.openclaw/workspace" "/tmp") for dir in "${allowed_dirs[@]}"; do if [[ "$resolved" == "$dir"* ]]; then return 0 fi done echo "Error: Path not allowed: $resolved" exit 1 } # 检查文件大小 check_file_size() { local path="$1" local size=$(stat -f%z "$path" 2>/dev/null || stat -c%s "$path" 2>/dev/null || echo 0) local max_size=$((100 * 1024 * 1024)) # 100MB if [[ $size -gt $max_size ]]; then echo "Warning: Large file ($size bytes), using streaming..." return 1 fi return 0 } # 读取文件 read_file() { local path="$1" # 检查文件存在 if [[ ! -f "$path" ]]; then echo "Error: File not found: $path" exit 1 fi # 验证路径 validate_path "$path" # 检查大小 if ! check_file_size "$path"; then # 大文件流式读取 tail -n +$((OFFSET + 1)) "$path" | head -n "$LIMIT" else # 小文件直接读取 tail -n +$((OFFSET + 1)) "$path" | head -n "$LIMIT" fi } # 主函数 main() { if [[ -z "$PATH" ]]; then echo "Error: --path is required" exit 1 fi read_file "$PATH" } main "$@"
文件: scripts/file-write.sh
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 #!/bin/bash set -ePATH="" CONTENT="" CREATE_DIRS=false BACKUP=true while [[ $# -gt 0 ]]; do case $1 in --path) PATH="$2 " shift 2 ;; --content) CONTENT="$2 " shift 2 ;; --create-dirs) CREATE_DIRS=true shift ;; --no-backup) BACKUP=false shift ;; *) echo "Unknown option: $1 " exit 1 ;; esac done backup_file () { local path="$1 " local backup_dir="$HOME /.openclaw/backups" local filename=$(basename "$path " ) local timestamp=$(date +%s) local backup_path="$backup_dir /$filename .$timestamp .backup" mkdir -p "$backup_dir " cp "$path " "$backup_path " echo "$backup_path " } atomic_write () { local path="$1 " local content="$2 " local temp_path="$path .tmp.$$" echo "$content " > "$temp_path " mv "$temp_path " "$path " } main () { if [[ -z "$PATH " ]] || [[ -z "$CONTENT " ]]; then echo "Error: --path and --content are required" exit 1 fi if [[ "$CREATE_DIRS " == true ]]; then mkdir -p "$(dirname "$PATH " ) " fi local backup_path="" if [[ -f "$PATH " ]] && [[ "$BACKUP " == true ]]; then backup_path=$(backup_file "$PATH " ) echo "Backup created: $backup_path " fi atomic_write "$PATH " "$CONTENT " echo "File written: $PATH " } main "$@ "
文件: scripts/file-edit.sh
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 #!/bin/bash set -ePATH="" CHANGES="" DRY_RUN=false while [[ $# -gt 0 ]]; do case $1 in --path) PATH="$2 " shift 2 ;; --changes) CHANGES="$2 " shift 2 ;; --dry-run) DRY_RUN=true shift ;; *) echo "Unknown option: $1 " exit 1 ;; esac done apply_changes () { local path="$1 " local changes="$2 " local content=$(cat "$path " ) local new_content="$content " local applied=0 local failed=0 echo "$changes " | grep -oP '"oldText"\s*:\s*"\K[^"]+' | while read -r old_text; do echo "$changes " | grep -oP '"newText"\s*:\s*"\K[^"]+' | while read -r new_text; do if [[ "$new_content " == *"$old_text " * ]]; then new_content="${new_content//$old_text/$new_text} " ((applied++)) else ((failed++)) fi done done echo "$new_content " } generate_diff () { local path="$1 " local old_content="$2 " local new_content="$3 " local old_file=$(mktemp ) local new_file=$(mktemp ) echo "$old_content " > "$old_file " echo "$new_content " > "$new_file " diff -u "$old_file " "$new_file " | sed "s|$old_file |$path |g" | sed "s|$new_file |$path |g" rm -f "$old_file " "$new_file " } main () { if [[ -z "$PATH " ]] || [[ -z "$CHANGES " ]]; then echo "Error: --path and --changes are required" exit 1 fi local original_content=$(cat "$PATH " ) local new_content=$(apply_changes "$PATH " "$CHANGES " ) local diff=$(generate_diff "$PATH " "$original_content " "$new_content " ) if [[ "$DRY_RUN " == true ]]; then echo "Dry run - changes preview:" echo "$diff " else local backup_path="$HOME /.openclaw/backups/$(basename "$PATH " ) .$(date +%s) .backup" mkdir -p "$(dirname "$backup_path " ) " cp "$PATH " "$backup_path " echo "Backup: $backup_path " echo "$new_content " > "$PATH " echo "File edited: $PATH " echo "" echo "Changes:" echo "$diff " fi } main "$@ "
步骤 4:编写测试用例 文件: tests/test.sh
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 #!/bin/bash set -eSCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]} " ) " && pwd) " PROJECT_DIR="$SCRIPT_DIR /test-project" TEST_PASSED=0 TEST_FAILED=0 setup () { mkdir -p "$PROJECT_DIR " echo "Hello World" > "$PROJECT_DIR /test.txt" echo "Setup complete" } teardown () { rm -rf "$PROJECT_DIR " echo "Cleanup complete" } test_read_file () { echo "Test: Read file..." local content=$(bash "$SCRIPT_DIR /../scripts/file-read.sh" --path "$PROJECT_DIR /test.txt" ) if [[ "$content " == "Hello World" ]]; then echo "✅ PASS" ((TEST_PASSED++)) else echo "❌ FAIL: Expected 'Hello World', got '$content '" ((TEST_FAILED++)) fi } test_write_file () { echo "Test: Write file..." local test_file="$PROJECT_DIR /write-test.txt" bash "$SCRIPT_DIR /../scripts/file-write.sh" \ --path "$test_file " \ --content "Test Content" if [[ -f "$test_file " ]] && [[ $(cat "$test_file " ) == "Test Content" ]]; then echo "✅ PASS" ((TEST_PASSED++)) else echo "❌ FAIL" ((TEST_FAILED++)) fi } test_edit_file () { echo "Test: Edit file..." bash "$SCRIPT_DIR /../scripts/file-edit.sh" \ --path "$PROJECT_DIR /test.txt" \ --changes '[{"oldText":"World","newText":"OpenClaw"}]' local content=$(cat "$PROJECT_DIR /test.txt" ) if [[ "$content " == "Hello OpenClaw" ]]; then echo "✅ PASS" ((TEST_PASSED++)) else echo "❌ FAIL: Expected 'Hello OpenClaw', got '$content '" ((TEST_FAILED++)) fi } test_path_validation () { echo "Test: Path validation..." if bash "$SCRIPT_DIR /../scripts/file-read.sh" --path "/etc/passwd" 2>&1 | grep -q "not allowed" ; then echo "✅ PASS" ((TEST_PASSED++)) else echo "❌ FAIL: Should reject /etc/passwd" ((TEST_FAILED++)) fi } test_backup () { echo "Test: Backup functionality..." local test_file="$PROJECT_DIR /backup-test.txt" echo "Original" > "$test_file " bash "$SCRIPT_DIR /../scripts/file-write.sh" \ --path "$test_file " \ --content "Modified" local backup_count=$(ls -1 "$HOME /.openclaw/backups/backup-test.txt." *.backup 2>/dev/null | wc -l) if [[ $backup_count -gt 0 ]]; then echo "✅ PASS" ((TEST_PASSED++)) else echo "❌ FAIL: No backup created" ((TEST_FAILED++)) fi } run_tests () { echo "==================================" echo "文件操作水晶包测试" echo "==================================" echo "" setup test_read_file test_write_file test_edit_file test_path_validation test_backup teardown echo "" echo "==================================" echo "测试结果:$TEST_PASSED 通过,$TEST_FAILED 失败" echo "==================================" if [[ $TEST_FAILED -gt 0 ]]; then exit 1 fi } run_tests
步骤 5:运行测试 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 bash tests/test.sh ================================== 文件操作水晶包测试 ================================== Setup complete Test: Read file... ✅ PASS Test: Write file... ✅ PASS Test: Edit file... ✅ PASS Test: Path validation... ✅ PASS Test: Backup functionality... ✅ PASS Cleanup complete ================================== 测试结果:5 通过,0 失败 ==================================
水晶包验证流程 验证清单 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 # 水晶包验证清单 ## 功能验证 - [ ] 所有功能正常工作- [ ] 边界条件处理正确- [ ] 错误处理完善## 安全验证 - [ ] 路径验证有效- [ ] 权限控制正常- [ ] 敏感信息脱敏## 性能验证 - [ ] 大文件处理正常- [ ] 内存使用合理- [ ] 响应时间可接受## 兼容性验证 - [ ] macOS 测试通过- [ ] Linux 测试通过- [ ] Windows (WSL) 测试通过## 文档验证 - [ ] CRYSTAL.md 完整- [ ] 使用示例清晰- [ ] API 文档准确
验证脚本 文件: scripts/verify.sh
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 #!/bin/bash set -eecho "水晶包验证开始..." echo "1. 检查文件结构..." required_files=("CRYSTAL.md" "package.json" "scripts/main.sh" "tests/test.sh" ) for file in "${required_files[@]} " ; do if [[ ! -f "$file " ]]; then echo "❌ 缺少必需文件:$file " exit 1 fi done echo "✅ 文件结构完整" echo "2. 运行测试..." bash tests/test.sh echo "✅ 测试通过" echo "3. 安全检查..." if grep -r "sk-[a-zA-Z0-9]+" scripts/ config/ 2>/dev/null; then echo "❌ 发现硬编码密钥" exit 1 fi echo "✅ 安全检查通过" echo "4. 文档检查..." if ! grep -q "name:" CRYSTAL.md; then echo "❌ CRYSTAL.md 缺少 name 字段" exit 1 fi if ! grep -q "version:" CRYSTAL.md; then echo "❌ CRYSTAL.md 缺少 version 字段" exit 1 fi echo "✅ 文档检查通过" echo "" echo "==================================" echo "水晶包验证完成!" echo "=================================="
水晶包发布与共享 发布到水晶包市场 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 cd ~/.openclaw/crystals/file-opstar -czf file-ops-1.0.0.tar.gz \ CRYSTAL.md \ package.json \ scripts/ \ config/ \ tests/ \ docs/ openclaw crystal publish file-ops-1.0.0.tar.gz 水晶包已发布: - 名称:file-ops - 版本:1.0.0 - ID: crystal_file-ops_1.0.0 - 市场链接:https://clawhub.ai/crystals/file-ops
安装水晶包 1 2 3 4 5 6 7 8 9 10 11 12 13 14 openclaw crystal install file-ops openclaw crystal install ./file-ops-1.0.0.tar.gz openclaw crystal list 已安装水晶包: - file-ops (1.0.0) - blog-publisher (2.0.0) - ...
使用水晶包 1 2 3 4 5 6 7 openclaw crystal file-ops --help openclaw run file-ops read --path "./test.txt" openclaw run file-ops write --path "./test.txt" --content "Hello" openclaw run file-ops edit --path "./test.txt" --changes '[{"oldText":"Hello","newText":"Hi"}]'
总结 核心要点
水晶包 = Claude Code 技能 + OpenClaw 规范
标准化能力 - 基于 20 个功能特性
完整验证 - 测试 + 文档 + 安全检查
可复用设计 - 任意 Agent 安装即用
市场分发 - 水晶包市场共享
实战成果
成果
说明
file-ops 水晶包
基于 Claude Code FileRead/Write/Edit Tool
完整测试
5 个测试用例全部通过
安全验证
路径验证、权限控制、密钥检查
文档完整
CRYSTAL.md + README + API 文档
下一步
系列文章:
[1-20] Claude Code 源码解析 (已完成)
[21] 水晶包开发完整指南 (本文)
[22+] 更多实战案例 (继续中…)
关于作者: John,OpenClaw 平台开发者,专注 AI 助手架构设计与实现。