Skill: wxwzl/files-memory-system (version 1.16.1)

--- name: files-memory-system description: Multi-context memory management system for OpenClaw agents with group-isolated storage, global shared memory, workspace organization, and group-specific skills isolation. Use when initializing or managing memory systems for multi-channel deployments, creating group-specific memory directories, setting up MEMORY.md for long-term cross-group memories, organizing workspace directories (projects/repos), cloning repositories to group-isolated locations, managing group-isolated skills, or handling any file operations in group chat contexts. --- # ⚠️ CRITICAL RULES ## 群聊中克隆仓库的硬性规定 **❌ 禁止**：直接使用 `git clone` 命令 **✅ 必须**：使用 `auto-clone.sh` 脚本并传入 `--group` 参数 当用户在群聊中要求"克隆仓库"时： 1. **不要**执行 `git clone <url>` → 这会克隆到 `/workspace/repos/` 2. **必须**执行 `./skills/files-memory-system/scripts/auto-clone.sh --group feishu <group_id> <url>` → 这会克隆到群组目录 **Group ID 获取方式**：从 metadata 中的 `conversation_label` 字段获取（如 `oc_a2b821...`） --- ## 🔴 会话开始强制检查清单 (群聊) **OpenClaw Bug: 群聊不会自动加载群记忆文件** 每次在群聊中收到消息时，**必须**执行以下检查： ``` 检查 metadata.is_group_chat: ├── IF true (群聊): │ ├── 读取 memory/group_<channel>_<conversation_label>/GLOBAL.md │ ├── 读取 memory/group_<channel>_<conversation_label>/YYYY-MM-DD.md (today) │ └── 读取 memory/global/GLOBAL.md │ └── IF false (私聊): ├── 读取 memory/private/YYYY-MM-DD.md (today) └── 读取 memory/global/GLOBAL.md ``` **禁止在群聊中执行任何操作前跳过此检查！** --- # Memory System > 📖 **新用户？** 请先阅读 [用户使用指南](references/USER_GUIDE.md) 了解如何快速上手！ ## Installation ### Method 1: Auto-Install with Self-Registration (Recommended) ```bash cd ~/.openclaw/skills/files-memory-system ./scripts/install.sh ``` This will: 1. ✅ Copy skill to [REDACTED_SECRET] (standard location) 2. ✅ Auto-register in `AGENTS.md` so the agent knows this skill exists 3. ✅ Enable auto-discovery on every agent startup ### Method 2: Manual Install ```bash # 1. Copy to standard location mkdir -p /workspace/skills cp -r ~/.openclaw/skills/files-memory-system /workspace/skills/ # 2. Run self-registration cd /workspace/skills/files-memory-system ./scripts/post-install.sh ``` ### Method 3: Using clawhub ```bash cd /workspace clawhub install files-memory-system # Then manually run: ./skills/files-memory-system/scripts/post-install.sh ``` ### Self-Registration Mechanism This skill implements **auto-declaration** - it automatically adds a section to `AGENTS.md` upon installation. This ensures: - The agent knows `files-memory-system` exists without being told - Memory locations are documented where the agent reads - No manual configuration needed after installation To verify registration: ```bash grep -A 20 "files-memory-system" /workspace/AGENTS.md ``` To unregister (remove from AGENTS.md): ```bash sed -i '/<!-- files-memory-system: installed -->/,/<!-- files-memory-system: end -->/d' /workspace/AGENTS.md ``` ## Overview This skill provides a complete memory management system that enables OpenClaw agents to maintain context across multiple chat groups while keeping group-specific memories and skills isolated. It includes: - **Group-isolated memory**: Separate memory directories per group/channel - **Group-isolated skills**: Skills installed per group, preventing cross-group pollution - **Global shared memory**: Cross-group knowledge in `memory/global/` - **Long-term memory**: `MEMORY.md` for curated, permanent memories - **Workspace organization**: Structured `projects/` and `repos/` directories ## Session Start - Automatic Memory Loading ⚠️ **重要**: 每次进入会话时，必须自动加载对应的记忆！ ### 群聊中的自动加载流程 当收到群聊消息时，按以下顺序加载记忆： 1. **读取群组 GLOBAL.md** - 获取群组关键信息和资源索引 ``` memory/group_<channel>_<id>/GLOBAL.md ``` 2. **读取今日和昨日记录** - 获取最近的对话上下文 ``` memory/group_<channel>_<id>/YYYY-MM-DD.md (today) memory/group_<channel>_<id>/YYYY-MM-DD.md (yesterday) ``` 3. **读取跨群组全局记忆** - 获取跨群组共享的信息 ``` memory/global/GLOBAL.md ``` ### 私聊中的自动加载流程 1. **读取私聊记录** - 今日和昨日 ``` memory/private/YYYY-MM-DD.md (today) memory/private/YYYY-MM-DD.md (yesterday) ``` 2. **读取跨群组全局记忆** ``` memory/global/GLOBAL.md ``` 3. **读取长期精华记忆** (仅私聊) ``` MEMORY.md ``` ### 记忆加载检查清单 **群聊中必须加载：** - [ ] 当前群组的 GLOBAL.md - [ ] 今天的群组日志 (YYYY-MM-DD.md) - [ ] 昨天的群组日志 (回顾上下文) - [ ] **跨群组全局记忆 (memory/global/GLOBAL.md)** **私聊中必须加载：** - [ ] 私聊今日和昨日日志 - [ ] **跨群组全局记忆 (memory/global/GLOBAL.md)** - [ ] MEMORY.md (仅私聊) ## Usage Scenarios ### Scenario 1: User Says "Clone This Repo" in a Group Chat **Context**: User in group "oc_a2b821..." says: "Clone https://github.com/user/project" **Automatic Actions**: 1. Detect current group context: `group_feishu_oc_a2b821...` 2. Clone to: `memory/group_feishu_oc_a2b821.../repos/project/` 3. Update group's GLOBAL.md with project info 4. Confirm: "✅ Cloned to group repos/project/" **Manual Commands**: ```bash # Option 1: Use auto-clone script with --group parameter (推荐) ./scripts/auto-clone.sh --group feishu oc_a2b821... https://github.com/user/project # Option 2: Direct git clone cd memory/group_feishu_xxx/repos git clone https://github.com/user/project # Option 3: Using environment variables (向后兼容) GROUP_ID="oc_xxx" CHANNEL="feishu" ./scripts/auto-clone.sh https://github.com/user/project ``` **Agent Implementation (直接执行，无需用户交互)**: 当用户要求克隆仓库时，**先判断当前是否在群聊中**（查看 inbound metadata 中的 `is_group_chat` 字段），然后： **如果是群聊** (`is_group_chat: true`): 1. 从 metadata 读取 `conversation_label` 作为 group_id 2. 使用 `--group` 参数执行克隆： ```bash ./skills/files-memory-system/scripts/auto-clone.sh \ --group feishu "<conversation_label>" \ "https://github.com/user/project" ``` **如果是私聊** (`is_group_chat: false`): ```bash ./skills/files-memory-system/scripts/auto-clone.sh \ --private \ "https://github.com/user/project" ``` **关键要点**： - ⚠️ **群聊中必须使用 `--group` 参数**，否则仓库会克隆到全局目录 - `--group <channel> <group_id>` 必须在 URL 之前 - 群组ID从 `conversation_label` 获取 (如 `oc_a2b821...`) - 脚本会自动创建缺失的群组记忆目录 - 如果用户没指定项目名称，脚本会自动从 URL 提取 **After Cloning - Update GLOBAL.md**: ```markdown ## 群组项目 (repos/) | 项目名称 | 类型 | 描述 | 位置 | |---------|------|------|------| | project | cloned | 克隆的示例项目 | repos/project/ | ``` ### Scenario 2: Create New Project in Group Context **Context**: User says: "Create a new tool for our group" **Automatic Actions**: 1. Create project directory: `memory/group_xxx/repos/my-tool/` 2. Initialize with template if needed 3. Update GLOBAL.md 4. Start working in the group-specific location **Manual Commands**: ```bash # Create new project in group context mkdir -p memory/group_feishu_xxx/repos/my-tool cd memory/group_feishu_xxx/repos/my-tool # ... create files ... ``` ### Scenario 3: Install Skill for Specific Group **Context**: User says: "Install inkos skill for this group only" **Automatic Actions**: 1. Install to: `memory/group_xxx/skills/inkos/` 2. Update group's GLOBAL.md 3. Skill is isolated to this group only **Manual Commands**: ```bash # Method 1: Using clawhub with --dir clawhub install inkos --dir memory/group_feishu_xxx/skills # Method 2: Manual copy mkdir -p memory/group_feishu_xxx/skills/inkos cp -r inkos/* memory/group_feishu_xxx/skills/inkos/ ``` **Update GLOBAL.md**: ```markdown ## 已安装的群组专属 Skills | Skill | 版本 | 来源 | 描述 | |-------|------|------|------| | inkos | 1.0.0 | clawhub | 小说写作工具 | ``` ### Scenario 4: Record Information to Group Memory ⭐ **Context**: User in group chat says: "记录到群记忆里: 项目信息" / "记录到全局记忆里: API密钥" / "记住这个" **Automatic Actions** (Agent Must Do): 1. **Detect the intent**: User wants to record information to group memory 2. **Determine target location** (按优先级匹配): - If "记录到群记忆里" → `memory/group_<channel>_<id>/GLOBAL.md` - If "记录到全局记忆里"/"记录到跨群记忆里" → `memory/global/GLOBAL.md` - If "记录到私聊里" → `memory/private/GLOBAL.md` - If "群文档"/"群组" (模糊指令) → `memory/group_<channel>_<id>/GLOBAL.md` 3. **Write to file immediately**: Do not just say "I remember", actually write to file! 4. **Confirm**: "✅ 已记录到群记忆" / "✅ 已保存到全局记忆" **Example 1: Record Project Info** ``` User: "记录到群记忆里: 项目信息" 项目名称: MyApp 技术栈: React + Node.js 负责人: 张三 Agent Action: 1. Detect "记录到群记忆里" → Target: memory/group_xxx/GLOBAL.md 2. Format as table and append: ## 活跃项目 | 项目名称 | 技术栈 | 负责人 | 更新时间 | |---------|--------|--------|----------| | MyApp | React + Node.js | 张三 | 2026-03-23 | 3. Confirm: "✅ 已记录到群记忆" ``` **Example 2: Record API Key (⚠️ Not Recommended)** ``` User: "记录到全局记忆里：API密钥 sk-abc123" ⚠️ **SECURITY WARNING**: Storing API keys in plain text in memory files is NOT recommended. **Recommended approach: Use environment variables** export [REDACTED_SECRET]" Alternative (if environment variables not possible): - Use a secrets manager - Use encrypted storage If user insists on storing in memory: 1. Warn: "⚠️ 存储 API 密钥到记忆文件存在安全风险，建议仅用于测试环境" 2. Detect target location based on user command 3. Format as table and append 4. Confirm: "✅ 已记录 (⚠️ 安全风险)" ``` **Recommended User Commands**: - "记录到群记忆里: [内容]" → 仅当前群可见 - "记录到全局记忆里: [内容]" → 所有群共享 - "记录到跨群记忆里: [内容]" → 同全局记忆 - "记录到私聊里: [内容]" → 仅私聊可见 **Critical Rules**: - ❌ DO NOT just say "I remember" without writing to file - ❌ DO NOT store sensitive info without clarifying scope - ✅ ALWAYS confirm the location where info is stored - ✅ Use tables in GLOBAL.md for structured info - ✅ Add timestamps for time-sensitive info ### Scenario 5: Create Files in Group Chat ⭐ **Context**: User in group chat says: "帮我写一篇文章" / "创建一个文档" / "生成xxx文件" **Automatic Actions** (Agent Must Do): 1. **Detect the intent**: User wants to create a file in group context 2. **Determine correct location**: - Default: `memory/group_<channel>_<id>/articles/` (for articles/docs) - Code: `memory/group_<channel>_<id>/repos/` (for code projects) 3. **Create the file**: Write to the correct group-specific path 4. **Auto-update GLOBAL.md**: ⚠️ **CRITICAL** - After creating file, auto-append to GLOBAL.md 5. **Confirm**: "✅ 已创建并记录到群文档" ### Scenario 6: Working Across Multiple Groups **Context**: Same user in different groups **Group A (小说创作)**: - Skills: `memory/group_A/skills/inkos/` - Projects: [REDACTED_SECRET] **Group B (编程学习)**: - Skills: [REDACTED_SECRET] - Projects: `memory/group_B/repos/exercises/` **Behavior**: - In Group A: Only sees `inkos`, not `code-helper` - In Group B: Only sees `code-helper`, not `inkos` - No pollution between groups! ### Scenario 5: Migrate Information to Global **Context**: Information becomes relevant to multiple groups **Migration Process**: 1. Move from: `memory/group_A/GLOBAL.md` 2. To: `memory/global/GLOBAL.md` 3. Update Group A with reference 4. All groups can now access **Example**: ```bash # Original in group_A/GLOBAL.md ## Project Configuration Config: xxx # After migration - in global/GLOBAL.md ## Shared Project Configuration Config: xxx # In group_A/GLOBAL.md - add reference ## 跨群组资源 See: memory/global/GLOBAL.md ``` ⚠️ **Security Note**: Do NOT migrate API keys, passwords, or other sensitive credentials to global memory. Keep secrets in environment variables or private memory only. ## Memory Architecture ### Directory Structure ``` /workspace/ ├── memory/ │ ├── global/ │ │ ├── GLOBAL.md # Shared key information │ │ └── YYYY-MM-DD.md # Daily logs │ ├── group_feishu_<id>/ # Feishu group memories │ │ ├── GLOBAL.md # Group key information │ │ ├── YYYY-MM-DD.md # Daily logs │ │ ├── skills/ # ⭐ Group-specific skills │ │ └── repos/ # ⭐ Group-specific projects │ └── private/ │ ├── GLOBAL.md │ └── YYYY-MM-DD.md ├── MEMORY.md ├── skills/ # Global shared skills ├── projects/ └── repos/ ``` ### Automation Scripts **scripts/init-group-memory.sh** - Initialize group memory structure: ```bash ./scripts/init-group-memory.sh feishu oc_xxx "小说创作群组" ``` **scripts/ensure-group-memory.sh** - Ensure group memory directory exists (on-demand): ```bash # Auto-initializes group memory with all subdirectories ./scripts/ensure-group-memory.sh feishu oc_xxx "小说创作群组" ``` **scripts/ensure-private-memory.sh** - Ensure private memory directory exists: ```bash # Auto-initializes private memory when in private chat context ./scripts/ensure-private-memory.sh ``` **scripts/ensure-global-memory.sh** - Ensure global memory directory exists: ```bash # Auto-initializes global memory for cross-group information ./scripts/ensure-global-memory.sh ``` **scripts/auto-clone.sh** - Clone repo to correct location: ```bash # Auto-detects context and clones to appropriate location ./scripts/auto-clone.sh https://github.com/user/repo ``` ## Group-Isolated Skills System | Scope | Location | Access | Priority | |-------|----------|--------|--------| | **Group-specific** | `memory/group_<id>/skills/` | Only current group | High | | **Global** | `/workspace/skills/` | All groups | Low | ## Promoting Cross-Group Memory Awareness ### 1. Include Reference in Group GLOBAL.md Every group's GLOBAL.md should include: ```markdown ## Cross-Group Resources 📚 **Cross-Group Global Memory**: `memory/global/GLOBAL.md` Contains information shared across all groups. ``` ### 2. Key Information to Store Globally - Relevant to multiple groups - Common standards or conventions - Shared resources (non-sensitive) - Tool documentation and links ⚠️ **Security Note**: Do NOT store API keys, passwords, or other sensitive credentials in global memory. Use environment variables or private memory for secrets. ### 3. Migration from Group to Global When information becomes relevant to multiple groups: 1. Move to `memory/global/GLOBAL.md` 2. Update original with reference link 3. Notify affected groups ## Memory Auto-Initialization All memory directories are automatically initialized using a dual approach (A + B): ### Approach A: Installation-Time Setup When installing files-memory-system, the following directories are automatically created: - `memory/private/` with `GLOBAL.md` - `memory/global/` with `GLOBAL.md` ### Approach B: On-Demand Setup When using `auto-clone.sh` or other scripts, the system automatically detects and initializes missing directories: - **Group context**: Calls `ensure-group-memory.sh` - **Private context**: Calls `ensure-private-memory.sh` - **Global operations**: Calls `ensure-global-memory.sh` This ensures all memory locations are always available when needed, even if: - The installation step was skipped - The directory was accidentally deleted - Working in a new workspace ### Memory Directory Comparison | Feature | Private Memory | Group Memory | Global Memory | |---------|----------------|--------------|---------------| | **Location** | `memory/private/` | `memory/group_<id>/` | `memory/global/` | | **Auto-init A** | ✅ Install-time | ❌ No | ✅ Install-time | | **Auto-init B** | ✅ On-demand | ✅ On-demand | ✅ On-demand | | **Skills** | Uses global | Can isolate | N/A | | **Projects** | Uses global | Can isolate | N/A | | **Scope** | 1-on-1 chats | Specific group | All groups | | **Ensure Script** | `ensure-private-memory.sh` | `ensure-group-memory.sh` | `ensure-global-memory.sh` | | **Scope** | 1-on-1 chats only | Specific to one group | | **Auto-init** | ✅ Yes (A+B) | ✅ Yes (B only) | ## Security Notes - `MEMORY.md` only loaded in private chats - Group skills completely isolated - Preserve group memory on disband

path: README.md
content: # Files Memory System

> 多上下文记忆管理系统，让 OpenClaw Agent 在多群组场景下井井有条

[![Version](https://img.shields.io/badge/version-1.14.0-blue.svg)](https://clawhub.com/skills/files-memory-system)
[![License](https://img.shields.io/badge/license-MIT-green.svg)](LICENSE)

## 🎯 项目简介

**Files Memory System** 是一个为 OpenClaw Agent 设计的**多上下文记忆管理系统**，解决 AI 助手在多个群组中缺乏**记忆持久化**的问题。

> OpenClaw 本身已有**会话隔离**（不同群组之间不会互相干扰），但每次新会话都是"一张白纸"，没有历史记忆。

### 核心能力

- 🏠 **群组隔离记忆** - 每个群组有独立的记忆空间
- 🌍 **全局共享记忆** - 跨群组的通用知识
- 🔒 **技能隔离** - 每个群组可以有专属的技能
- 📁 **项目隔离** - 每个群组可以有专属的项目目录
- 🤖 **自动加载** - 进入群聊自动加载该群的记忆

## 🚀 快速开始

### 安装

```bash
# 从 ClawHub 安装
clawhub install files-memory-system

# 运行安装脚本
cd /workspace/skills/files-memory-system
./scripts/install.sh
```

安装完成后，系统会自动：
- 创建私聊记忆目录
- 创建全局共享记忆目录
- 注册到 AGENTS.md（Agent 启动时自动识别）

### 使用

**无需手动操作！** 当 Agent 进入群聊时，会自动：
1. 加载该群组的 GLOBAL.md
2. 加载今日和昨日的对话记录
3. 加载跨群组全局记忆

你只需要正常使用 AI，其他的交给系统自动处理。

## 📂 目录结构

```
/workspace/
├── memory/
│   ├── global/                    # 全局共享记忆
│   │   ├── GLOBAL.md
│   │   └── YYYY-MM-DD.md
│   ├── group_feishu_<id>/         # 群组专属记忆
│   │   ├── GLOBAL.md
│   │   ├── YYYY-MM-DD.md
│   │   ├── skills/
│   │   └── repos/
│   └── private/                   # 私聊记忆
│       ├── GLOBAL.md
│       └── YYYY-MM-DD.md
├── MEMORY.md                      # 长期核心记忆（仅私聊）
└── skills/                        # 全局共享技能
```

## 💡 使用场景

### 场景1：群聊中克隆项目

**用户说**："克隆 https://github.com/user/project"

**系统自动**：
- 识别当前群组
- 克隆到该群组的 repos/ 目录
- 更新 GLOBAL.md 记录
- 其他群组完全不可见

### 场景2：安装群组专属技能

```bash
clawhub install inkos --dir memory/group_feishu_<id>/skills
```

该技能仅当前群组可用，完美隔离。

### 场景3：跨群组共享信息

将信息从群组移动到 `memory/global/GLOBAL.md`，所有群组都能访问。

## 🔧 可用脚本

| 脚本 | 用途 |
|------|------|
| `install.sh` | 安装 skill，初始化基础目录 |
| `post-install.sh` | 自注册到 AGENTS.md |
| `init-group-memory.sh` | 初始化群组记忆结构 |
| `ensure-group-memory.sh` | 确保群组目录存在（按需创建） |
| `ensure-private-memory.sh` | 确保私聊目录存在 |
| `ensure-global-memory.sh` | 确保全局目录存在 |
| `auto-clone.sh` | 自动克隆仓库到正确位置 |

## 🛠️ 开发

### 环境要求

- OpenClaw >= 2026.3.0
- Bash >= 4.0
- Git

### 开发流程

```bash
# 1. 克隆源码
git clone https://gitee.com/wxwzl-ai/files-memory-system.git
cd files-memory-system

# 2. 修改代码
# ...

# 3. 提交并推送
git add .
git commit -m "feat: your changes"
git push origin master

# 4. 发布到 ClawHub
clawhub publish . --version x.x.x
```

### 目录规范

- **原始源码**：`~/.openclaw/skills/files-memory-system/`
- **工作区**：`/workspace/skills/files-memory-system/`（通过 clawhub 安装）
- **发布**：ClawHub Registry

## 📝 记录规则

| 场景 | 写入位置 |
|------|----------|
| 群聊对话 | `memory/group_<channel>_<id>/YYYY-MM-DD.md` |
| 私聊对话 | `memory/private/YYYY-MM-DD.md` |
| 跨群组通用信息 | `memory/global/GLOBAL.md` |
| 长期精华记忆 | `MEMORY.md` |

## 🔍 记忆加载优先级

1. **当前群组目录**（最高优先级）
2. **全局目录**
3. **其他群组**（仅在必要时）

## 🔒 安全特性

- `MEMORY.md` **仅在私聊中加载**
- 群组技能完全隔离
- 群组解散后记忆保留（历史审计）
- 敏感信息过滤（自动）

## 📚 文档

- [用户使用指南](references/USER_GUIDE.md) - 面向最终用户
- [架构设计说明](references/architecture.md) - 面向开发者
- [SKILL.md](SKILL.md) - Skill 完整技术文档

## 🤝 贡献

欢迎提交 Issue 和 PR！

1. Fork 本仓库
2. 创建特性分支 (`git checkout -b feature/AmazingFeature`)
3. 提交更改 (`git commit -m 'Add some AmazingFeature'`)
4. 推送到分支 (`git push origin feature/AmazingFeature`)
5. 创建 Pull Request

## 📄 许可证

[MIT](LICENSE) © wxwzl

## 🔗 链接

- **GitHub**: https://gitee.com/wxwzl-ai/files-memory-system
- **ClawHub**: https://clawhub.com/skills/files-memory-system
- **问题反馈**: https://gitee.com/wxwzl-ai/files-memory-system/issues

---

> **记忆口诀**：群聊产出归群管，私聊产出归私管，全局共享放 global


path: SECURITY.md
content: # 安全实践指南 - 文件删除机制

> 本文档记录 files-memory-system 中文件删除的安全实践，避免后续改动破坏安全机制。

## 🎯 核心原则

**永远优先使用 `trash` 命令，避免直接使用 `rm -rf`**

## 📋 背景

### 问题来源
- 原始 `install.sh` 使用 `rm -rf` 删除旧版本 skill
- 被 VirusTotal 标记为 suspicious patterns
- 触发安全警报："检测到潜在危险操作"

### 解决方案
使用 `trash` 命令代替 `rm -rf`：
- 文件移至回收站，可恢复
- 避免永久删除
- 符合现代操作系统标准行为

## 🔧 实现机制

### 当前实现 (install.sh)

```bash
# 安全删除逻辑
if command -v trash &> /dev/null; then
    trash "$TARGET_DIR"
    echo "   ✅ 已移至回收站 (trash)"
else
    rm -rf "$TARGET_DIR"
    echo "   ✅ 已删除 (rm -rf)"
fi
```

### 关键特性

| 特性 | 说明 |
|------|------|
| **优先 trash** | 如果系统有 trash 命令，优先使用 |
| **回退机制** | trash 不可用时，回退到 rm -rf |
| **用户确认** | 删除前必须用户输入 y 确认 |
| **明确提示** | 显示要删除的路径、原因、影响范围 |

## ⚠️ 重要提醒

### 不要这样做

❌ **不要恢复使用纯 `rm -rf`**
```bash
# 危险！不要这样改
rm -rf "$TARGET_DIR"  # 永久删除，无法恢复
```

❌ **不要删除用户确认步骤**
```bash
# 危险！不要这样改
# 删除前不询问用户
```

❌ **不要扩大删除范围**
```bash
# 危险！不要这样改
rm -rf /workspace/  # 会删除所有数据！
```

### 应该这样做

✅ **保持 trash 优先逻辑**
```bash
if command -v trash &> /dev/null; then
    trash "$TARGET_DIR"
else
    rm -rf "$TARGET_DIR"
fi
```

✅ **保持用户确认**
```bash
read -p "确认删除? (y/N): " confirm
if [[ $confirm != [yY] ]]; then
    exit 0
fi
```

✅ **保持明确提示**
```bash
echo "即将删除: $TARGET_DIR"
echo "(仅删除此 skill 目录，不影响其他数据)"
```

## 📝 更新记录

| 日期 | 改动 | 作者 |
|------|------|------|
| 2026-03-24 | 使用 trash 代替 rm -rf | files-memory-system 开发群组 |
| 2026-03-24 | 增强删除前提示信息 | files-memory-system 开发群组 |

## 🔗 相关文件

- `scripts/install.sh` - 包含安全删除逻辑
- `SECURITY.md` - 本文档

## 📚 参考

- [trash-cli 项目](https://github.com/andreafrancia/trash-cli) - 跨平台的 trash 命令实现
- [VirusTotal 安全扫描](https://www.virustotal.com) - 文件安全检测平台

---

**最后更新**: 2026-03-24
**维护者**: files-memory-system 开发群组


path: _meta.json
content: {
  "name": "files-memory-system",
  "version": "1.16.1",
  "description": "Multi-context memory management system for OpenClaw agents with group-isolated storage, global shared memory, workspace organization, and group-specific skills isolation. CRITICAL FIX: Added mandatory manual memory loading check for group chats due to OpenClaw auto-loading bug. Use --group parameter for git clone in group contexts.",
  "author": "wxwzl",
  "license": "MIT",
  "repository": {
    "type": "git",
    "url": "https://clawhub.com/skills/files-memory-system"
  },
  "keywords": [
    "memory",
    "group-isolation",
    "multi-context",
    "workspace-organization",
    "auto-loading"
  ],
  "lastUpdated": "2026-03-26",
  "dependencies": {
    "openclaw": ">=2026.3.0"
  }
}


path: assets/templates/GLOBAL-template.md
content: # GLOBAL.md - {群组名称}

## 群组信息
- **主题**: {群组主题}
- **平台**: {飞书/Discord/其他}
- **ID**: {群组ID}

## 关键信息
_(重要规则、常用信息、决策记录等)_

## 成员
_(重要成员信息)_

## 常用资源
_(工具链接、参考资料、模板等)_

## 重要决策
_(群组内做出的重要决定)_

## 已安装的群组专属 Skills

| Skill | 版本 | 来源 | 描述 |
|-------|------|------|------|
| _(待添加)_ | - | - | - |

**说明**: 以上 skills 仅在本群组可用，其他群组无法访问。

## 群组项目 (repos/)

| 项目名称 | 类型 | 描述 | 位置 |
|---------|------|------|------|
| _(待添加)_ | own/cloned | - | repos/xxx/ |

**说明**: 
- **类型**: `own` = 本群组创建的代码项目, `cloned` = 克隆的开源项目
- 以上项目存放在本群组专属的 repos/ 目录下

## 跨群组资源

📚 **跨群组全局记忆**: `memory/global/GLOBAL.md`

包含跨所有群组共享的信息：
- 通用工具链接和配置（非敏感）
- 跨群组的规则和标准
- 公开的共享知识

⚠️ **安全提醒**: 不要将 API 密钥、密码等敏感凭证存储在此处。敏感信息请使用环境变量或私聊记忆。

---
Last updated: {YYYY-MM-DD}


path: assets/templates/MEMORY-template.md
content: # MEMORY.md - 长期精华记忆

## 记忆系统架构

### 目录结构
```
memory/
├── global/                          # 通用记忆（跨群组共享）
│   ├── GLOBAL.md                    # 全局关键信息汇总
│   └── YYYY-MM-DD.md                # 按日期的记录
├── group_feishu_<id>/              # 飞书群专属记忆
│   ├── GLOBAL.md                    # 群组全局关键信息
│   └── YYYY-MM-DD.md                # 按日期的记录
├── group_discord_<id>/             # Discord 群专属记忆
│   ├── GLOBAL.md                    # 群组全局关键信息
│   └── YYYY-MM-DD.md                # 按日期的记录
├── private/                         # 1对1私聊记忆
│   ├── GLOBAL.md                    # 私聊全局关键信息
│   └── YYYY-MM-DD.md                # 按日期的记录
└── MEMORY.md                        # 长期精华记忆（仅私聊加载）
```

### 记录规则

| 场景 | 写入位置 |
|------|----------|
| 群聊中的对话 | `memory/group_<channel>_<id>/YYYY-MM-DD.md` |
| 私聊中的对话 | `memory/private/YYYY-MM-DD.md` |
| 主动说"记住这个" | `memory/global/YYYY-MM-DD.md` |
| 跨群组通用的知识 | `memory/global/GLOBAL.md` |
| 当前群组的关键信息 | `memory/group_<channel>_<id>/GLOBAL.md` |
| 提炼的长期记忆 | `MEMORY.md` |

### 文件类型说明

| 文件 | 用途 |
|------|------|
| `GLOBAL.md` | 该目录的全局关键信息汇总（快速查阅） |
| `YYYY-MM-DD.md` | 按日期的原始记录 |
| `MEMORY.md` | 跨所有群组的精华记忆（仅私聊加载） |

---

## 工作区目录规范

### 代码项目存放规则
```
/workspace/
├── projects/          # 自己编写的程序
│   └── <project-name>/
└── repos/             # 开源项目 / 克隆的项目
    └── <repo-name>/
```

| 目录 | 用途 | 操作 |
|------|------|------|
| `projects/` | 自己写的程序 | 新建项目文件存放于此 |
| `repos/` | 开源项目 | 克隆开源项目存放于此 |

- 查找自己写过的程序 → 去 `projects/` 下查找
- 查找开源项目 → 去 `repos/` 下查找

---

## 长期记忆

_(记录跨群组的重要信息、用户偏好、项目上下文等)_

---
Last updated: {YYYY-MM-DD}


path: assets/templates/daily-log-template.md
content: # {YYYY-MM-DD} - 记录标题

## 今日概要
_(简要总结今天的重要事项)_

## 详细记录

### 事件/话题 1
_(详细描述)_

### 事件/话题 2
_(详细描述)_

## 学到的/记住的
_(值得记录的经验、决策、信息)_

## 待办/跟进
_(需要后续处理的事项)_

---
Stored at: {timestamp}
Location: {memory_location}


path: memory/private/GLOBAL.md
content: # GLOBAL.md - 私聊记忆

## 私聊信息
- **类型**: 1对1私聊
- **用途**: 记录私聊中的重要信息和对话

## 重要信息
_(私聊中的重要决定、偏好设置、个人笔记等)_

## 常用资源
_(私聊中分享的链接、工具、参考资料等)_

## 跨群组资源

📚 **跨群组全局记忆**: `memory/global/GLOBAL.md`

包含跨所有群组共享的信息。

---
Last updated: $(date +%Y-%m-%d)


path: references/USER_GUIDE.md
content: # Files Memory System - 用户使用指南

## 📖 简介

**Files Memory System** 是一个为 OpenClaw Agent 设计的**多上下文记忆管理系统**。

### 它能做什么？

- 🏠 **群组隔离记忆** - 每个聊天群组有独立的记忆空间
- 🌍 **全局共享记忆** - 跨群组的通用知识
- 🔒 **技能隔离** - 每个群组可以有专属的技能
- 📁 **项目隔离** - 每个群组可以有专属的项目目录

---

## 🚀 快速开始

### 第一步：安装 Skill

```bash
# 从 ClawHub 安装
clawhub install files-memory-system

# 进入 skill 目录
 cd /workspace/skills/files-memory-system

# 运行安装脚本（自动创建基础目录）
./scripts/install.sh
```

安装完成后，会自动创建：
- `memory/private/` - 私聊记忆
- `memory/global/` - 全局共享记忆

> 💡 **提示**：群组记忆的初始化是**自动**的！当 Agent 进入群聊并需要记录信息时，会自动创建 `memory/group_xxx/` 目录结构，无需手动执行初始化脚本。

---

## 📂 记忆目录结构

```
/workspace/
├── memory/
│   ├── global/              # 📚 跨群组共享
│   │   ├── GLOBAL.md        # 全局关键信息
│   │   └── 2024-01-15.md    # 每日记录
│   ├── group_feishu_xxx/    # 👥 群组专属
│   │   ├── GLOBAL.md        # 群组信息
│   │   ├── 2024-01-15.md    # 每日记录
│   │   ├── skills/          # 群组技能
│   │   └── repos/           # 群组项目
│   └── private/             # 🔒 私聊专属
│       ├── GLOBAL.md
│       └── 2024-01-15.md
└── MEMORY.md                # 🧠 长期精华记忆
```

---

## 💡 使用场景

### 场景 1：在群聊中克隆项目

**你说**："克隆这个仓库 https://github.com/user/project"

**系统自动处理**：
1. 识别你在当前群组
2. 把项目克隆到该群专属的项目文件夹
3. 更新群文档记录，方便以后查找

**你不用关心**：项目存在哪里、路径是什么，系统会自动处理。

---

### 场景 2：给群安装专属工具

**你说**："给这个群安装 inkos 写作助手"

**系统自动处理**：
1. 在当前群安装 inkos 工具
2. 该工具仅当前群可用，其他群看不到
3. 更新群的工具清单

**你不用关心**：安装路径、怎么隔离，系统自动确保工具只在当前群可用。

---

### 场景 3：记录重要信息

**使用明确的指令格式**：

| 你说的话 | Agent 会这样做 | 记录位置 |
|---------|---------------|---------|
| "记录到群记忆里: 项目架构讨论" | 写入群组记忆 | `memory/group_xxx/GLOBAL.md` |
| "记录到全局记忆里: API 密钥 xxx" | 写入全局共享 | `memory/global/GLOBAL.md` |
| "记录到跨群记忆里: 团队规范" | 写入全局共享 | `memory/global/GLOBAL.md` |
| "记录到私聊里: 个人笔记" | 写入私聊记忆 | `memory/private/GLOBAL.md` |

**💡 提示**：使用 "记录到X记忆里" 的格式，Agent 会立即写入对应位置，而不会只是口头说"我记住了"。

---

## 📝 记录规则速查

| 你想记录什么 | 使用指令 | 写入哪里 | 安全提示 |
|-------------|---------|---------|---------|
| 仅当前群组可见的信息 | "记录到群记忆里: xxx" | `memory/group_xxx/GLOBAL.md` | 适合一般信息 |
| 所有群组共享的信息 | "记录到全局记忆里: xxx" | `memory/global/GLOBAL.md` | ⚠️ 不要存储敏感凭证 |
| 跨群共享（同全局） | "记录到跨群记忆里: xxx" | `memory/global/GLOBAL.md` | ⚠️ 不要存储敏感凭证 |
| 仅私聊可见的信息 | "记录到私聊里: xxx" | `memory/private/GLOBAL.md` | 适合个人笔记，⚠️ 不存储敏感凭证 |
| 今日对话记录 | 自动 | `memory/group_xxx/YYYY-MM-DD.md` | - |

---

## 🔍 搜索优先级

当 Agent 搜索记忆时，按以下顺序：
1. **当前群组目录** - 最相关
2. **全局目录** - 跨群组共享
3. **其他群组** - 仅在必要时

---

## ❓ 常见问题

### Q: 为什么需要群组隔离？
**A**: 防止不同群组的记忆互相污染。比如小说创作群和编程学习群的 skill 不应该混在一起。

### Q: 群组解散了怎么办？
**A**: 记忆会保留在 `memory/group_xxx/` 中，不会删除。可用于历史回顾或重新激活群组时恢复上下文。

### Q: 如何迁移信息到全局？
**A**: 使用指令 "记录到全局记忆里"，或把内容从群记忆移动到 `memory/global/GLOBAL.md`。

### Q: Agent 怎么知道这些目录？
**A**: 安装时系统会自动注册，Agent 启动时会读取配置，你不需要手动设置。

### Q: 我可以存储 API 密钥或密码吗？
**A**: ⚠️ **不可以**。不要将敏感凭证（API 密钥、密码、Token）存储在记忆系统中：
- **✅ 推荐**: 使用环境变量（`export API_KEY="xxx"`）
- **❌ 避免**: 不要存储在"记录到群记忆里"
- **❌ 避免**: 不要存储在"记录到全局记忆里"
- **❌ 避免**: 不要存储在"记录到私聊里"

所有记忆文件都是明文存储，不适合保存敏感信息。

---

## 🔒 安全最佳实践

### 敏感信息处理
| 信息类型 | 推荐存储方式 | 风险等级 |
|---------|-------------|---------|
| API 密钥、Token | **环境变量** | ✅ 安全 |
| 密码 | **环境变量** | ✅ 安全 |
| 个人敏感信息 | **环境变量** | ✅ 安全 |
| 一般配置信息 | 群/全局记忆 | ✅ 安全 |
| 公开文档链接 | 群/全局记忆 | ✅ 安全 |

⚠️ **重要提醒**：**不要将任何敏感凭证（API 密钥、密码、Token）存储在记忆系统中**。始终使用环境变量存储敏感信息。

### 环境变量设置方法

1. **在启动前设置环境变量**（推荐方式）：
   - 在终端配置文件（如 ~/.bashrc、~/.zshrc 或 ~/.bash_profile）中添加环境变量定义
   - 或在启动 OpenClaw 前临时导出：`export 变量名="值"`

2. **运行时告知 AI**：
   - 告诉 AI："使用环境变量中的 API 密钥"
   - AI 会自动读取已设置的环境变量，无需在对话中暴露凭证

3. **安全提示**：
   - 不要在聊天记录、记忆文件或代码中直接写入敏感凭证
   - 环境变量仅在当前会话有效，不会持久化到磁盘上的记忆文件

---

## 📚 进阶阅读

### 技术文档
- `SKILL.md` - 完整技术文档
- `references/architecture.md` - 架构设计说明

### 可用脚本（技术用户）
| 脚本 | 用途 |
|------|------|
| `install.sh` | 安装 skill |
| `auto-clone.sh` | 自动克隆项目 |
| `ensure-group-memory.sh` | 确保群组目录 |
| `ensure-global-memory.sh` | 确保全局目录 |

### 模板文件
- `assets/templates/` - 各种模板文件

---

## 🆘 获取帮助

如果在 ClawHub 上查看此 skill，可以：
1. 阅读 `SKILL.md` 获取完整技术细节
2. 查看 `references/architecture.md` 了解架构设计
3. 运行 `./scripts/install.sh --help` 查看安装选项

---

**版本**: v1.10.2  
**作者**: wxwzl  
**许可证**: MIT


path: references/architecture.md
content: # 记忆系统架构

## 概述

本记忆系统实现了按群组隔离的记忆存储方案，支持多平台（飞书、Discord 等）群聊的独立记忆管理，同时保留跨群组共享的全局记忆能力。此外，系统还支持**群组专属技能隔离**，确保不同群组的技能不会互相污染。

## 目录结构

### 记忆目录

```
memory/
├── global/                          # 通用记忆（跨群组共享）
│   ├── GLOBAL.md                    # 全局关键信息汇总
│   └── YYYY-MM-DD.md                # 按日期的记录
├── group_feishu_<id>/              # 飞书群专属记忆
│   ├── GLOBAL.md                    # 群组全局关键信息
│   ├── YYYY-MM-DD.md                # 按日期的记录
│   ├── skills/                      # ⭐ 群组专属技能（隔离）
│   │   ├── skill-a/
│   │   └── skill-b/
│   └── repos/                       # ⭐ 群组专属项目
│       ├── my-project/              # 本群组创建的代码
│       └── cloned-repo/             # 为本群组克隆的项目
├── group_discord_<id>/             # Discord 群专属记忆
│   ├── GLOBAL.md                    # 群组全局关键信息
│   ├── YYYY-MM-DD.md                # 按日期的记录
│   ├── skills/                      # ⭐ 群组专属技能（隔离）
│   │   └── group-only-skill/
│   └── repos/                       # ⭐ 群组专属项目
├── private/                         # 1对1私聊记忆
│   ├── GLOBAL.md                    # 私聊全局关键信息
│   └── YYYY-MM-DD.md                # 按日期的记录
└── MEMORY.md                        # 长期精华记忆（仅私聊加载）
```

### 工作区目录

```
/workspace/
├── memory/                          # 记忆系统根目录
├── skills/                          # 全局共享技能
│   ├── inkos/
│   └── files-memory-system/
├── projects/                        # 自己编写的程序
│   └── <project-name>/
├── repos/                           # 开源项目 / 克隆的项目
│   └── <repo-name>/
└── MEMORY.md                        # 长期精华记忆
```

## 文件类型说明

| 文件 | 用途 |
|------|------|
| `GLOBAL.md` | 该目录的全局关键信息汇总（快速查阅） |
| `YYYY-MM-DD.md` | 按日期的详细对话记录 |
| `MEMORY.md` | 跨所有群组的长期精华记忆（仅私聊加载） |

## 记录规则

| 场景 | 写入位置 |
|------|----------|
| 群聊中的对话 | `memory/group_<channel>_<id>/YYYY-MM-DD.md` |
| 私聊中的对话 | `memory/private/YYYY-MM-DD.md` |
| 主动说"记住这个" | `memory/global/YYYY-MM-DD.md` |
| 跨群组通用的知识 | `memory/global/GLOBAL.md` |
| 当前群组的关键信息 | `memory/group_<channel>_<id>/GLOBAL.md` |
| 提炼的长期记忆 | `MEMORY.md` |

## 技能隔离系统

### 技能类型

| 类型 | 位置 | 访问范围 | 优先级 |
|------|------|----------|--------|
| 群组专属技能 | `memory/group_<id>/skills/` | 仅当前群组 | 高（覆盖全局） |
| 全局技能 | `/workspace/skills/` | 所有群组 | 低 |

### 技能加载优先级

当在某个群组上下文中时，技能加载顺序：
1. **首先搜索** `memory/group_<id>/skills/` - 群组专属技能
2. **然后搜索** `/workspace/skills/` - 全局共享技能
3. **同名冲突** - 群组版本优先于全局版本

### 技能安装方法

#### 方法1：使用 clawhub CLI
```bash
# 安装到特定群组
clawhub install <skill-name> --dir memory/group_feishu_<id>/skills
```

#### 方法2：手动安装
```bash
# 创建技能目录
mkdir -p memory/group_feishu_<id>/skills/my-skill

# 复制技能文件
cp -r my-skill/* memory/group_feishu_<id>/skills/my-skill/
```

### 记录已安装技能

安装后应在群组的 `GLOBAL.md` 中记录：

```markdown
## 已安装的群组专属 Skills

| Skill | 版本 | 来源 | 描述 |
|-------|------|------|------|
| inkos | 1.0.0 | clawhub | 小说写作工具 |
| custom-skill | 0.5.0 | manual | 本群组定制功能 |
```

### 技能隔离的好处

1. **防止污染**：小说写作技能不会影响编程群组
2. **定制化**：每个群组可以有专属的技能版本
3. **安全性**：群组技能无法访问其他群组的记忆
4. **灵活性**：全局技能提供基础，群组技能提供定制

## 项目隔离系统

每个群组可以有自己独立的 `repos/` 目录，用于存放：
- 在群组讨论中创建的代码项目
- 为群组特定需求克隆的开源项目

### 项目类型

| 类型 | 位置 | 说明 |
|------|------|------|
| **群组专属项目** | `memory/group_<id>/repos/` | 仅在本群组上下文使用 |
| **全局项目** | `/workspace/projects/` 或 `/workspace/repos/` | 跨群组共享 |

### 项目存储规则

| 场景 | 存储位置 |
|------|----------|
| 在群组中编写的代码 | `memory/group_<id>/repos/<project>/` |
| 为群组克隆的仓库 | `memory/group_<id>/repos/<repo>/` |
| 跨群组共享的项目 | `/workspace/projects/` 或 `/workspace/repos/` |

### 记录群组项目

在群组的 `GLOBAL.md` 中记录项目信息：

```markdown
## 群组项目 (repos/)

| 项目名称 | 类型 | 描述 | 位置 |
|---------|------|------|------|
| my-tool | own | 本群组创建的工具 | repos/my-tool/ |
| inkos | cloned | 克隆的小说写作工具 | repos/inkos/ |
```

### 项目隔离的好处

1. **上下文保持**：项目与创建它的群组上下文绑定
2. **减少混乱**：全局工作区保持整洁
3. **易于交接**：新成员通过 GLOBAL.md 了解群组项目
4. **高效搜索**：在群组中工作时，相关项目立即可用

## 搜索优先级

### 记忆搜索
搜索记忆时，按以下优先级顺序：
1. 当前群组目录（如 `group_feishu_xxx/`）
2. `memory/global/` 目录
3. 其他群组目录（仅在必要时）

### 技能搜索
搜索技能时，按以下优先级顺序：
1. 当前群组的 `skills/` 目录
2. 全局的 `/workspace/skills/` 目录
3. 系统默认 skills 目录

### 项目搜索
搜索代码项目时，按以下优先级顺序：
1. 当前群组的 `repos/` 目录（如果在群组上下文中）
2. `/workspace/projects/` - 全局自有项目
3. `/workspace/repos/` - 全局克隆项目

## 工作区目录规范

```
/workspace/
├── projects/          # 自己编写的程序
│   └── <project-name>/
└── repos/             # 开源项目 / 克隆的项目
    └── <repo-name>/
```

| 目录 | 用途 | 操作 |
|------|------|------|
| `projects/` | 自己写的程序 | 新建项目文件存放于此 |
| `repos/` | 开源项目 | 克隆开源项目存放于此 |

## 初始化步骤

### 1. 初始化全局记忆
```bash
mkdir -p memory/{global,private}
touch memory/global/GLOBAL.md
```

### 2. 初始化群组记忆
```bash
mkdir -p memory/group_<channel>_<id>
touch memory/group_<channel>_<id>/GLOBAL.md
touch memory/group_<channel>_<id>/YYYY-MM-DD.md
```

### 3. 初始化群组技能目录和项目目录
```bash
mkdir -p memory/group_<channel>_<id>/skills
mkdir -p memory/group_<channel>_<id>/repos
```

### 4. 初始化工作区
```bash
mkdir -p projects repos
touch MEMORY.md
```

## 安全注意事项

- `MEMORY.md` 仅在私聊时加载，避免群聊中泄露个人敏感信息
- 群聊记忆仅对应当前群组成员可见
- **群组技能完全隔离**，无法被其他群组访问
- **群组解散时保留记忆** - 当群组解散时，不删除 `memory/group_<channel>_<id>/` 目录下的所有记忆文件。这些文件保留用于：
  - 历史回顾和审计
  - 重新激活群组时恢复上下文
  - 数据分析和知识提取
- 定期审查 `MEMORY.md` 中的内容，移除过时或敏感信息
- 群组专属 skills 不应随意共享到其他群组


path: scripts/auto-clone.sh
content: #!/bin/bash
# auto-clone.sh - 自动克隆项目到正确的目录
# 根据当前上下文决定克隆位置
#
# 用法:
#   方式1 - 参数传入 (推荐):
#     ./auto-clone.sh --group <channel> <group_id> <repo_url> [project_name]
#
#   方式2 - 参数传入 (私聊):
#     ./auto-clone.sh --private <repo_url> [project_name]
#
#   方式3 - 环境变量 (向后兼容):
#     GROUP_ID="oc_xxx" CHANNEL="feishu" ./auto-clone.sh <repo_url> [project_name]
#
#   方式4 - 全局 (无上下文):
#     ./auto-clone.sh <repo_url> [project_name]

set -e

# 解析参数
GROUP_CHANNEL=""
GROUP_ID=""
IS_PRIVATE=""
REPO_URL=""
PROJECT_NAME=""

while [[ $# -gt 0 ]]; do
    case $1 in
        --group)
            GROUP_CHANNEL="$2"
            GROUP_ID="$3"
            shift 3
            ;;
        --private)
            IS_PRIVATE="1"
            shift
            ;;
        --help|-h)
            echo "用法: $0 [选项] <repo_url> [project_name]"
            echo ""
            echo "选项:"
            echo "  --group <channel> <group_id>  克隆到指定群组目录"
            echo "  --private                    克隆到私聊目录"
            echo "  --help, -h                   显示帮助"
            echo ""
            echo "示例:"
            echo "  $0 --group feishu oc_xxx https://github.com/user/repo"
            echo "  $0 --private https://github.com/user/repo my-project"
            echo "  $0 https://github.com/user/repo  # 克隆到全局 repos/"
            exit 0
            ;;
        -*)
            echo "❌ 未知选项: $1"
            echo "用法: $0 --help 查看帮助"
            exit 1
            ;;
        *)
            # 第一个非选项参数是 repo_url
            if [ -z "$REPO_URL" ]; then
                REPO_URL="$1"
            else
                # 第二个非选项参数是 project_name
                PROJECT_NAME="$1"
            fi
            shift
            ;;
    esac
done

# 验证必需参数
if [ -z "$REPO_URL" ]; then
    echo "❌ 错误: 需要提供仓库 URL"
    echo "用法: $0 [选项] <repo_url> [project_name]"
    exit 1
fi

# 如果 project_name 没提供，从 URL 提取
if [ -z "$PROJECT_NAME" ]; then
    PROJECT_NAME=$(basename "$REPO_URL" .git)
fi

# 如果命令行没传，从环境变量获取 (向后兼容)
if [ -z "$GROUP_CHANNEL" ] && [ -n "$CHANNEL" ]; then
    GROUP_CHANNEL="$CHANNEL"
fi
if [ -z "$GROUP_ID" ] && [ -n "$GROUP_ID" ]; then
    # 注意：这里用 GROUP_ID 环境变量
    GROUP_ID="$GROUP_ID"
fi

# 确定目标位置
if [ -n "$GROUP_CHANNEL" ] && [ -n "$GROUP_ID" ]; then
    # 在群组上下文中 - 先确保目录存在
    SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
    bash "$SCRIPT_DIR/ensure-group-memory.sh" "$GROUP_CHANNEL" "$GROUP_ID"

    GROUP_DIR="memory/group_${GROUP_CHANNEL}_${GROUP_ID}"
    TARGET_DIR="${GROUP_DIR}/repos/${PROJECT_NAME}"

    echo "📁 检测到群组上下文，克隆到: ${TARGET_DIR}"

elif [ -n "$IS_PRIVATE" ]; then
    # 在私聊上下文中 - 先确保目录存在
    SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
    bash "$SCRIPT_DIR/ensure-private-memory.sh"

    PRIVATE_DIR="memory/private"
    TARGET_DIR="${PRIVATE_DIR}/repos/${PROJECT_NAME}"

    echo "📁 检测到私聊上下文，克隆到: ${TARGET_DIR}"

else
    # 默认到全局 - 先确保全局记忆目录存在
    SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
    bash "$SCRIPT_DIR/ensure-global-memory.sh"

    TARGET_DIR="repos/${PROJECT_NAME}"

    # 确保目录存在
    mkdir -p "repos"

    echo "📁 未检测到特定上下文，克隆到全局: ${TARGET_DIR}"
fi

# 检查目标是否已存在
if [ -d "$TARGET_DIR" ]; then
    echo "⚠️  目标目录已存在: ${TARGET_DIR}"
    echo "💡 如需重新克隆，请先删除该目录"
    exit 1
fi

# 克隆
echo "🔄 正在克隆 ${REPO_URL}..."
git clone "$REPO_URL" "$TARGET_DIR"

echo ""
echo "✅ 克隆完成: ${TARGET_DIR}"
echo "📝 记得更新 GLOBAL.md 记录此项目！"
echo ""
echo "项目内容:"
ls -la "$TARGET_DIR"

path: scripts/auto-load-group-memory.sh
content: #!/bin/bash
# auto-load-group-memory.sh - 自动加载群记忆（带防重复标记）
#
# 用法: ./auto-load-group-memory.sh <channel> <group_id>
#
# 功能:
# - 检查今天是否已经加载过群记忆
# - 如果没有，加载 GLOBAL.md + 今日/昨日记录
# - 创建标记文件避免重复加载

set -e

CHANNEL="${1:-feishu}"
GROUP_ID="${2:-}"

if [ -z "$GROUP_ID" ]; then
    echo "❌ 错误: 需要提供 group_id"
    echo "用法: $0 <channel> <group_id>"
    exit 1
fi

GROUP_DIR="memory/group_${CHANNEL}_${GROUP_ID}"
MARKER_FILE="${GROUP_DIR}/.memory-loaded"
TODAY=$(date +%Y-%m-%d)

# 检查是否已经加载过（今天）
if [ -f "$MARKER_FILE" ]; then
    LAST_LOADED=$(cat "$MARKER_FILE" 2>/dev/null || echo "")
    if [ "$LAST_LOADED" = "$TODAY" ]; then
        echo "✅ 群记忆今天已加载 ($TODAY)"
        exit 0
    fi
fi

# 加载群记忆
echo "📚 正在加载群记忆..."

if [ -f "${GROUP_DIR}/GLOBAL.md" ]; then
    echo "✅ GLOBAL.md"
fi

if [ -f "${GROUP_DIR}/${TODAY}.md" ]; then
    echo "✅ ${TODAY}.md (今日)"
fi

YESTERDAY=$(date -d "yesterday" +%Y-%m-%d 2>/dev/null || date -v-1d +%Y-%m-%d)
if [ -f "${GROUP_DIR}/${YESTERDAY}.md" ]; then
    echo "✅ ${YESTERDAY}.md (昨日)"
fi

if [ -f "memory/global/GLOBAL.md" ]; then
    echo "✅ global/GLOBAL.md"
fi

# 更新标记
echo "$TODAY" > "$MARKER_FILE"
echo "📝 已更新加载标记: $MARKER_FILE"

echo "✅ 群记忆加载完成"

path: scripts/ensure-global-memory.sh
content: #!/bin/bash
# ensure-global-memory.sh - 确保全局记忆目录存在（方案 B：按需自动创建）
# 当需要记录跨群组信息时调用，自动初始化缺失的目录和文件

set -e

GLOBAL_DIR="${1:-memory/global}"
TODAY=$(date +%Y-%m-%d)

echo "🔍 检查全局记忆目录: ${GLOBAL_DIR}..."

# 创建基础目录
if [ ! -d "$GLOBAL_DIR" ]; then
    echo "⚠️  全局目录不存在，正在初始化..."
    mkdir -p "$GLOBAL_DIR"
    echo "✅ 创建 ${GLOBAL_DIR}"
fi

# 创建 GLOBAL.md（如果不存在）
if [ ! -f "$GLOBAL_DIR/GLOBAL.md" ]; then
    cat > "$GLOBAL_DIR/GLOBAL.md" << EOF
# GLOBAL.md - 跨群组全局记忆

## 概述
本文件包含跨所有群组共享的信息，所有群组都可以访问。

## 重要工具与凭证

_(记录跨群组的工具链接、配置说明、共享资源等)_

## 跨群组通用规则

_(所有群组都应遵守的规则和标准)_

## 全局项目

_(跨群组共享的项目信息)_

---
Last updated: ${TODAY}
EOF
    echo "✅ 创建 ${GLOBAL_DIR}/GLOBAL.md"
fi

# 创建今日记录文件（如果不存在）
if [ ! -f "$GLOBAL_DIR/${TODAY}.md" ]; then
    cat > "$GLOBAL_DIR/${TODAY}.md" << EOF
# ${TODAY} - 全局记录

## 今日概要
_(简要总结今天的跨群组事项)_

## 详细记录

### 事件/话题 1
_(详细描述)_

## 学到的/记住的
_(值得记录的全局经验、决策、信息)_

---
Stored at: $(date '+%Y-%m-%d %H:%M:%S')
Location: ${GLOBAL_DIR}/
EOF
    echo "✅ 创建 ${GLOBAL_DIR}/${TODAY}.md"
fi

echo "✅ 全局记忆目录检查完成"


path: scripts/ensure-group-memory.sh
content: #!/bin/bash
# ensure-group-memory.sh - 确保群组记忆目录存在（方案 B：按需自动创建）
# 当检测到群组上下文时调用，自动初始化缺失的目录和文件

set -e

GROUP_CHANNEL="${1:-feishu}"
GROUP_ID="${2:-}"
GROUP_NAME="${3:-}"

if [ -z "$GROUP_ID" ]; then
    echo "❌ 错误: 需要提供群组 ID"
    echo "用法: $0 <channel> <group_id> [group_name]"
    echo "示例: $0 feishu oc_xxx '小说创作群组'"
    exit 1
fi

GROUP_DIR="memory/group_${GROUP_CHANNEL}_${GROUP_ID}"
TODAY=$(date +%Y-%m-%d)

echo "🔍 检查群组记忆目录: ${GROUP_DIR}..."

# 创建基础目录
if [ ! -d "$GROUP_DIR" ]; then
    echo "⚠️  群组目录不存在，正在初始化..."
    mkdir -p "$GROUP_DIR"
    echo "✅ 创建 ${GROUP_DIR}"
fi

# 确保子目录存在
mkdir -p "$GROUP_DIR/skills"
mkdir -p "$GROUP_DIR/repos"
echo "✅ 确保 skills/ 和 repos/ 子目录存在"

# 创建 GLOBAL.md（如果不存在）
if [ ! -f "$GROUP_DIR/GLOBAL.md" ]; then
    cat > "$GROUP_DIR/GLOBAL.md" << EOF
# GLOBAL.md - ${GROUP_NAME:-群组 ${GROUP_ID}}

## 群组信息
- **主题**: ${GROUP_NAME:-待填写}
- **平台**: ${GROUP_CHANNEL}
- **ID**: ${GROUP_ID}

## 关键信息
_(重要规则、常用信息、决策记录等)_

## 成员
_(重要成员信息)_

## 常用资源
_(工具链接、参考资料、模板等)_

## 重要决策
_(群组内做出的重要决定)_

## 已安装的群组专属 Skills

| Skill | 版本 | 来源 | 描述 |
|-------|------|------|------|
| _(待添加)_ | - | - | - |

## 群组项目 (repos/)

| 项目名称 | 类型 | 描述 | 位置 |
|---------|------|------|------|
| _(待添加)_ | own/cloned | - | repos/xxx/ |

## 跨群组资源

📚 **跨群组全局记忆**: \`memory/global/GLOBAL.md\`

包含跨所有群组共享的信息。

---
Last updated: ${TODAY}
EOF
    echo "✅ 创建 ${GROUP_DIR}/GLOBAL.md"
fi

# 创建今日记录文件（如果不存在）
if [ ! -f "$GROUP_DIR/${TODAY}.md" ]; then
    cat > "$GROUP_DIR/${TODAY}.md" << EOF
# ${TODAY} - 群组记录

## 今日概要
_(简要总结今天的重要事项)_

## 详细记录

### 事件/话题 1
_(详细描述)_

## 学到的/记住的
_(值得记录的经验、决策、信息)_

---
Stored at: $(date '+%Y-%m-%d %H:%M:%S')
Location: ${GROUP_DIR}/
EOF
    echo "✅ 创建 ${GROUP_DIR}/${TODAY}.md"
fi

echo "✅ 群组记忆目录检查完成"


path: scripts/ensure-private-memory.sh
content: #!/bin/bash
# ensure-private-memory.sh - 确保私聊记忆目录存在（方案 B：按需自动创建）
# 当检测到私聊上下文时调用，自动初始化缺失的目录和文件

set -e

PRIVATE_DIR="${1:-memory/private}"
TODAY=$(date +%Y-%m-%d)

echo "🔍 检查私聊记忆目录..."

# 创建基础目录
if [ ! -d "$PRIVATE_DIR" ]; then
    echo "⚠️  私聊记忆目录不存在，正在初始化..."
    mkdir -p "$PRIVATE_DIR"
    echo "✅ 创建 $PRIVATE_DIR"
fi

# 创建 GLOBAL.md（如果不存在）
if [ ! -f "$PRIVATE_DIR/GLOBAL.md" ]; then
    cat > "$PRIVATE_DIR/GLOBAL.md" << EOF
# GLOBAL.md - 私聊记忆

## 私聊信息
- **类型**: 1对1私聊
- **用途**: 记录私聊中的重要信息和对话

## 重要信息
_(私聊中的重要决定、偏好设置、个人笔记等)_

## 常用资源
_(私聊中分享的链接、工具、参考资料等)_

## 跨群组资源

📚 **跨群组全局记忆**: \`memory/global/GLOBAL.md\`

包含跨所有群组共享的信息。

---
Last updated: $TODAY
EOF
    echo "✅ 创建 $PRIVATE_DIR/GLOBAL.md"
fi

# 创建今日记录文件（如果不存在）
if [ ! -f "$PRIVATE_DIR/$TODAY.md" ]; then
    cat > "$PRIVATE_DIR/$TODAY.md" << EOF
# $TODAY - 私聊记录

## 今日概要
_(简要总结今天的重要事项)_

## 详细记录

### 事件/话题 1
_(详细描述)_

## 学到的/记住的
_(值得记录的经验、决策、信息)_

---
Stored at: $(date '+%Y-%m-%d %H:%M:%S')
Location: $PRIVATE_DIR/
EOF
    echo "✅ 创建 $PRIVATE_DIR/$TODAY.md"
fi

# 如果需要 repos 子目录，也确保它存在
if [ ! -d "$PRIVATE_DIR/repos" ]; then
    mkdir -p "$PRIVATE_DIR/repos"
    echo "✅ 创建 $PRIVATE_DIR/repos"
fi

echo "✅ 私聊记忆目录检查完成"


path: scripts/init-group-memory.sh
content: #!/bin/bash
# init-group-memory.sh - 初始化群组记忆结构

GROUP_CHANNEL="$1"  # e.g., "feishu"
GROUP_ID="$2"       # e.g., "oc_xxx"
GROUP_NAME="$3"     # e.g., "小说创作群组"

if [ -z "$GROUP_CHANNEL" ] || [ -z "$GROUP_ID" ]; then
    echo "Usage: $0 <channel> <group_id> [group_name]"
    echo "Example: $0 feishu oc_xxx '小说创作群组'"
    exit 1
fi

GROUP_DIR="memory/group_${GROUP_CHANNEL}_${GROUP_ID}"

echo "📁 创建群组记忆目录: ${GROUP_DIR}"
mkdir -p "${GROUP_DIR}/skills"
mkdir -p "${GROUP_DIR}/repos"

echo "📝 创建 GLOBAL.md..."
cat > "${GROUP_DIR}/GLOBAL.md" << EOF
# GLOBAL.md - ${GROUP_NAME:-群组}

## 群组信息
- **主题**: ${GROUP_NAME:-待填写}
- **平台**: ${GROUP_CHANNEL}
- **ID**: ${GROUP_ID}

## 关键信息
_(重要规则、常用信息、决策记录等)_

## 成员
_(重要成员信息)_

## 常用资源
_(工具链接、参考资料、模板等)_

## 重要决策
_(群组内做出的重要决定)_

## 已安装的群组专属 Skills

| Skill | 版本 | 来源 | 描述 |
|-------|------|------|------|
| _(待添加)_ | - | - | - |

## 群组项目 (repos/)

| 项目名称 | 类型 | 描述 | 位置 |
|---------|------|------|------|
| _(待添加)_ | own/cloned | - | repos/xxx/ |

## 跨群组资源

📚 **跨群组全局记忆**: \`memory/global/GLOBAL.md\`

包含跨所有群组共享的信息。

---
Last updated: $(date +%Y-%m-%d)
EOF

echo "📝 创建今日记录文件..."
TODAY=$(date +%Y-%m-%d)
cat > "${GROUP_DIR}/${TODAY}.md" << EOF
# ${TODAY} - 群组初始化

## 今日概要
群组记忆系统初始化完成。

## 详细记录

### 群组信息
- **主题**: ${GROUP_NAME:-待填写}
- **平台**: ${GROUP_CHANNEL}
- **ID**: ${GROUP_ID}

---
Stored at: $(date '+%Y-%m-%d %H:%M:%S')
Location: ${GROUP_DIR}/
EOF

echo "✅ 群组记忆初始化完成！"
echo ""
echo "📂 目录结构:"
tree -L 2 "${GROUP_DIR}" 2>/dev/null || ls -la "${GROUP_DIR}"


path: scripts/install.sh
content: #!/bin/bash
# install.sh - Install files-memory-system to standard location with self-registration

set -e

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
TARGET_DIR="/workspace/skills/files-memory-system"

echo "🧠 Installing files-memory-system..."

# 检查是否在正确的上下文
if [ ! -d "/workspace" ]; then
    echo "❌ Error: /workspace not found"
    echo "   This skill must be installed in an OpenClaw workspace"
    exit 1
fi

# 创建目标目录
mkdir -p /workspace/skills

# 初始化私聊记忆目录（方案 A：安装时自动创建）
echo "📝 初始化私聊记忆目录..."
mkdir -p /workspace/memory/private
if [ ! -f "/workspace/memory/private/GLOBAL.md" ]; then
    cat > /workspace/memory/private/GLOBAL.md << EOF
# GLOBAL.md - 私聊记忆

## 私聊信息
- **类型**: 1对1私聊
- **用途**: 记录私聊中的重要信息和对话

## 重要信息
_(私聊中的重要决定、偏好设置、个人笔记等)_

## 常用资源
_(私聊中分享的链接、工具、参考资料等)_

## 跨群组资源

📚 **跨群组全局记忆**: \`memory/global/GLOBAL.md\`

包含跨所有群组共享的信息。

---
Last updated: $(date +%Y-%m-%d)
EOF
    echo "✅ 创建 /workspace/memory/private/GLOBAL.md"
else
    echo "✅ 私聊记忆目录已存在"
fi

# 初始化全局记忆目录（方案 A：安装时自动创建）
echo "📝 初始化全局记忆目录..."
mkdir -p /workspace/memory/global
if [ ! -f "/workspace/memory/global/GLOBAL.md" ]; then
    cat > /workspace/memory/global/GLOBAL.md << EOF
# GLOBAL.md - 跨群组全局记忆

## 概述
本文件包含跨所有群组共享的信息，所有群组都可以访问。

## 重要工具与凭证

_(记录跨群组的工具链接、配置说明、共享资源等)_

## 跨群组通用规则

_(所有群组都应遵守的规则和标准)_

## 全局项目

_(跨群组共享的项目信息)_

---
Last updated: $(date +%Y-%m-%d)
EOF
    echo "✅ 创建 /workspace/memory/global/GLOBAL.md"
else
    echo "✅ 全局记忆目录已存在"
fi

# 复制 skill 到标准位置
if [ -d "$TARGET_DIR" ]; then
    echo ""
    echo "⚠️  检测到已存在的安装"
    echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
    echo "目标目录: $TARGET_DIR"
    echo "目录内容:"
    ls -la "$TARGET_DIR" | head -10
    echo ""
    echo "❓ 为什么要删除?"
    echo "   重新安装/升级需要删除旧版本，避免文件冲突"
    echo "   删除后将从当前目录复制最新版本"
    echo ""
    echo "⚠️  即将删除: $TARGET_DIR"
    echo "   (仅删除此 skill 目录，不影响记忆数据和其他文件)"
    echo ""
    read -p "   确认删除并重新安装? (y/N): " confirm
    if [[ $confirm != [yY] ]]; then
        echo "   已取消，保留现有版本"
        exit 0
    fi
    echo "   正在删除: $TARGET_DIR ..."
    # 使用 trash 命令安全删除（移到回收站），如不可用则回退到 rm
    if command -v trash &> /dev/null; then
        trash "$TARGET_DIR"
        echo "   ✅ 已移至回收站 (trash)"
    else
        rm -rf "$TARGET_DIR"
        echo "   ✅ 已删除 (rm -rf)"
    fi
fi

cp -r "$SCRIPT_DIR/.." "$TARGET_DIR"
echo "✅ Copied skill to $TARGET_DIR"

# 运行自注册
cd "$TARGET_DIR"
if [ -f "scripts/post-install.sh" ]; then
    bash scripts/post-install.sh
fi

echo ""
echo "🎉 Installation complete!"
echo ""
echo "Next steps:"
echo "1. The agent will now auto-discover files-memory-system on startup"
echo "2. Check AGENTS.md to see the registration"
echo "3. Initialize your first group memory with:"
echo "   ./scripts/init-group-memory.sh <channel> <group-id> <name>"


path: scripts/post-install.sh
content: #!/bin/bash
# post-install.sh - Files Memory System Self-Registration
# 安装后自动向 AGENTS.md 声明自身存在

set -e

SKILL_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
AGENTS_FILE="/workspace/AGENTS.md"
MARKER="<!-- files-memory-system: installed -->"

echo "📝 Running files-memory-system post-install..."

# 检查 AGENTS.md 是否存在
if [ ! -f "$AGENTS_FILE" ]; then
    echo "⚠️  AGENTS.md not found at $AGENTS_FILE"
    echo "   Please ensure you're installing in /workspace context"
    exit 0
fi

# 检查是否已经注册过
if grep -q "$MARKER" "$AGENTS_FILE" 2>/dev/null; then
    echo "✅ Files memory system already registered in AGENTS.md"
    exit 0
fi

# 添加到 AGENTS.md
cat >> "$AGENTS_FILE" << 'EOF'

<!-- files-memory-system: installed -->
## Files Memory System (Auto-Registered)

This workspace has the **files-memory-system** skill installed.

### Available Memory Locations
- **Global**: `memory/global/` - Cross-group shared memory
- **Group-specific**: `memory/group_<channel>_<id>/` - Isolated per group
- **Private**: `memory/private/` - 1-on-1 chat only

### Key Files
- `MEMORY.md` - Long-term curated memory (private chats only)
- `GLOBAL.md` - Quick reference in each memory directory
- `YYYY-MM-DD.md` - Daily logs

### Session Start - Memory Loading Rules ⭐

**⚠️ 群聊中必须自动加载：**
1. `memory/group_<channel>_<id>/GLOBAL.md` - 群组关键信息
2. `memory/group_<channel>_<id>/YYYY-MM-DD.md` (today) - 今日记录
3. `memory/group_<channel>_<id>/YYYY-MM-DD.md` (yesterday) - 昨日记录
4. `memory/global/GLOBAL.md` - **跨群组全局共享记忆**

**私聊中自动加载：**
1. `memory/private/YYYY-MM-DD.md` (today + yesterday)
2. `memory/global/GLOBAL.md` - **跨群组全局共享记忆**
3. `MEMORY.md` (仅私聊)

**🔴 重要：群聊自动加载失效 Workaround (2026-03-26)**

当前 OpenClaw 版本在群聊中**不会自动加载**群记忆文件。

**Agent 必须在会话开始时手动加载：**
```
IF is_group_chat == true:
  1. 从 metadata 获取 conversation_label (如: oc_a2b821...)
  2. 构建路径: memory/group_feishu_<conversation_label>/
  3. 手动读取:
     - GLOBAL.md
     - YYYY-MM-DD.md (today)
     - YYYY-MM-DD.md (yesterday)  
     - memory/global/GLOBAL.md
```

**检查清单** (群聊中执行任何操作前):
- [ ] 已读取群组 GLOBAL.md?
- [ ] 已读取今日群组日志?
- [ ] 已读取全局 GLOBAL.md?

### When to Use
- User says "remember this" → Write to appropriate location
- User asks "what did we discuss" → Search memory directories
- User wants group isolation → Use group-specific paths
- Cross-group knowledge → Use global/

### Auto-Discovery Note
This section was auto-added by files-memory-system post-install.
<!-- files-memory-system: end -->
EOF

echo "✅ Registered files-memory-system in AGENTS.md"
echo "   Agent will now auto-discover this skill on startup"


Security scan verdicts — ClawScan: suspicious | static analysis: clean | VirusTotal: clean | SkillSpector: suspicious (CRITICAL)