📋 Manus式持久化规划Skill实战

📅 更新:2026-05-24 | ⏱️ 阅读时间:12分钟 | 🏷️ 标签:Manus规划, OpenClaw Skill, 持久化规划, 项目管理

📋 目录

1. 什么是Manus式规划?

凌晨3点47分,我看着一份20页的项目规划文档发呆。突然想起Manus——那个被$2B收购的AI项目管理工具——它的核心秘密不是AI多聪明,而是持久化的Markdown规划文件

Manus式规划的核心思想:

💡 一句话: Manus式规划 = AI Agent界的「甘特图 + 看板 + 持续集成」三合一。

2. 为什么要持久化规划?

问题 无持久化 Manus式持久化
Agent重启 ❌ 丢失所有规划 ✅ 从文件恢复
长周期项目 ❌ 上下文超限 ✅ 文件按需加载
多人协作 ❌ 无法共享 ✅ Git版本控制
进度追踪 ❌ 动态调整困难 ✅ 实时更新状态
审计回溯 ❌ 无记录 ✅ Git历史完整

3. Skill结构设计

skills/planning-with-files/
├── SKILL.md              # Skill描述
├── index.js              # 主逻辑
├── templates/            # 规划模板
│   ├── project.md        # 项目规划模板
│   ├── sprint.md        # 迭代规划模板
│   └── task.md          # 任务模板
├── utils/
│   ├── parser.js         # Markdown解析
│   ├── tracker.js        # 进度追踪
│   └── validator.js      # 规划校验
└── tests/
    └── planning.test.js

4. 完整实现代码

4.1 SKILL.md

# planning-with-files

Manus-style persistent markdown planning for OpenClaw.

## Description
Implements persistent project planning using markdown files, 
enabling long-running projects with task decomposition, progress 
tracking, and dynamic plan adjustments.

## Usage
- "Create a project plan for [project name]"
- "Update task [task-id] to completed"
- "Show me the current project status"
- "Add a new task to sprint 2"

## Features
- ✅ Persistent markdown-based planning
- ✅ Automatic task dependency tracking  
- ✅ Progress visualization
- ✅ Git integration for version control
- ✅ Context-efficient (load only what's needed)

4.2 核心实现(index.js)

import fs from 'fs';
import path from 'path';

export default {
  name: "planning-with-files",
  description: "Manus-style persistent markdown planning",
  
  async execute(context, query) {
    const planDir = context.config.planDir || './plans';
    await fs.promises.mkdir(planDir, { recursive: true });
    
    if (query.match(/create.*plan/i)) {
      return await this.createProjectPlan(context, query, planDir);
    } else if (query.match(/update.*task/i)) {
      return await this.updateTask(context, query, planDir);
    } else if (query.match(/status|progress/i)) {
      return await this.showProgress(context, planDir);
    }
  },

  async createProjectPlan(context, query, planDir) {
    const projectName = query.match(/for\s+(.+?)(?:\s|$)/i)?.[1] || 'New Project';
    const planFile = path.join(planDir, `${this.slugify(projectName)}.md`);
    
    const planContent = `# ${projectName} - Project Plan

> Created: ${new Date().toISOString().split('T')[0]}
> Status: 🟡 In Progress

## 📊 Overview
- **Goal**: [Define your project goal]
- **Timeline**: [Start date] → [End date]
- **Owner**: [Team/Person]

## 🎯 Milestones

### Milestone 1: [Name] (Due: YYYY-MM-DD)
- [ ] Task 1.1: [Description]
- [ ] Task 1.2: [Description]

### Milestone 2: [Name] (Due: YYYY-MM-DD)
- [ ] Task 2.1: [Description]

## ✅ Completed Tasks
*(Automatically updated when tasks are marked complete)*

## 📝 Notes
- Add project-specific notes here
`;
    
    await fs.promises.writeFile(planFile, planContent, 'utf8');
    return `✅ Project plan created: ${planFile}\n\n${planContent}`;
  },

  async updateTask(context, query, planDir) {
    const taskMatch = query.match(/task\s+([\w.-]+)/i);
    if (!taskMatch) return "❌ Please specify a task ID (e.g., '1.1' or '2.3')";
    
    const taskId = taskMatch[1];
    // Find and update the task in the markdown file
    const files = await fs.promises.readdir(planDir);
    const planFile = files.find(f => f.endsWith('.md'));
    
    if (!planFile) return "❌ No project plan found. Create one first.";
    
    let content = await fs.promises.readFile(path.join(planDir, planFile), 'utf8');
    
    // Toggle task status
    const taskRegex = new RegExp(`(- \\[)([ x])(\\]\\s+Task\\s+${taskId.replace('.', '\\.')})`, 'i');
    const match = content.match(taskRegex);
    
    if (!match) return `❌ Task ${taskId} not found in the plan.`;
    
    const newStatus = match[2] === ' ' ? 'x' : ' ';
    content = content.replace(taskRegex, `$1${newStatus}$3`);
    
    // Move completed tasks to the "Completed" section
    if (newStatus === 'x') {
      const completedSection = '## ✅ Completed Tasks\n';
      const insertPos = content.indexOf(completedSection) + completedSection.length;
      const taskLine = `- [x] Task ${taskId} (completed: ${new Date().toISOString().split('T')[0]})\n`;
      content = content.slice(0, insertPos) + taskLine + content.slice(insertPos);
    }
    
    await fs.promises.writeFile(path.join(planDir, planFile), content, 'utf8');
    return `✅ Task ${taskId} marked as ${newStatus === 'x' ? 'completed ✅' : 'pending ⏳'}`;
  },

  async showProgress(context, planDir) {
    const files = await fs.promises.readdir(planDir);
    const planFile = files.find(f => f.endsWith('.md'));
    
    if (!planFile) return "❌ No project plan found.";
    
    const content = await fs.promises.readFile(path.join(planDir, planFile), 'utf8');
    
    const totalTasks = (content.match(/- \[[ x]\]/g) || []).length;
    const completedTasks = (content.match(/- \[x\]/g) || []).length;
    const progress = totalTasks > 0 ? Math.round((completedTasks / totalTasks) * 100) : 0;
    
    const progressBar = '█'.repeat(Math.floor(progress / 5)) + '░'.repeat(20 - Math.floor(progress / 5));
    
    return `📊 **Project Progress**

${progressBar} ${progress}%

- Total Tasks: ${totalTasks}
- Completed: ${completedTasks}
- Remaining: ${totalTasks - completedTasks}

📄 Plan file: ${planFile}`;
  },

  slugify(text) {
    return text.toLowerCase().replace(/[^\w]+/g, '-').replace(/^-+|-+$/g, '');
  }
};

5. Markdown规划文件格式

一个标准的规划文件应该包含:

# [项目名称] - Project Plan

> Created: 2026-05-24
> Status: 🟡 In Progress
> Owner: AI Team

## 📊 Overview
- **Goal**: 实现OpenClaw多Agent协作框架
- **Timeline**: 2026-05-24 → 2026-06-30
- **Priority**: P0

## 🎯 Milestones

### M1: 基础架构 (Due: 2026-06-07)
- [x] Task 1.1: 设计Agent通信协议 (completed: 2026-05-25)
- [x] Task 1.2: 实现消息队列
- [ ] Task 1.3: 编写单元测试

### M2: Skills集成 (Due: 2026-06-21)
- [ ] Task 2.1: 开发Skills加载器
- [ ] Task 2.2: 实现热重载机制

## ✅ Completed Tasks
- [x] Task 1.1: 设计Agent通信协议 (completed: 2026-05-25)

## 📝 Notes
- 使用Redis做消息队列
- Skills热重载需要文件监听

6. 使用案例

案例1:启动新项目

用户: "Create a project plan for OpenClaw Discord Bot"

Agent (使用planning-with-files skill):
✅ Project plan created: ./plans/openclaw-discord-bot.md

# OpenClaw Discord Bot - Project Plan
> Created: 2026-05-24
> Status: 🟡 In Progress

## 📊 Overview
- **Goal**: 开发Discord语音跟随功能
- **Timeline**: 2026-05-24 → 2026-06-15
...

案例2:更新任务状态

用户: "Update task 1.1 to completed"

Agent:
✅ Task 1.1 marked as completed ✅

(规划文件自动更新,任务移到"Completed Tasks"区)

案例3:查看进度

用户: "Show me the current project status"

Agent:
📊 **Project Progress**

████████████░░░░░░░░░░░░  50%

- Total Tasks: 10
- Completed: 5
- Remaining: 5

7. 与OpenClaw集成

7.1 安装Skill

# 方法1: 从ClawHub安装
clawhub install planning-with-files

# 方法2: 手动安装
cp -r planning-with-files ~/.openclaw/skills/

# 验证安装
openclaw skills list | grep planning

7.2 配置

// ~/.openclaw/config.json
{
  "skills": {
    "planning-with-files": {
      "enabled": true,
      "planDir": "./project-plans",
      "autoGitCommit": true,
      "gitMessage": "chore: update project plan"
    }
  }
}

7.3 Git集成(可选)

自动将规划文件变更提交到Git:

{
  "autoGitCommit": true,
  "gitHook": {
    "preCommit": "npm test",
    "postCommit": "git push origin main"
  }
}

8. 常见问题

Q1: 规划文件太大怎么办?

答: 拆分为多个文件:

plans/
├── project-overview.md    # 总览
├── milestones/
│   ├── m1-architecture.md
│   ├── m2-skills.md
│   └── m3-deployment.md
└── daily/
    ├── 2026-05-24.md
    └── 2026-05-25.md

Q2: 如何与团队共享规划?

答:plans/ 目录加入Git版本控制,团队成员克隆仓库即可同步。

Q3: Agent重启后如何恢复规划状态?

答: 规划状态全部存储在Markdown文件中,Agent重启后只需重新读取文件即可恢复。无需额外的状态管理。

🎯 总结: Manus式规划的核心不是技术有多牛,而是「让规划本身成为可维护的文档」。就像王家卫电影里那些看似随意却精心设计的镜头——每个Markdown文件都是项目历史的见证者。

🔗 相关资源


🦞 妙趣AI - 让AI工具变得有趣又实用 | 返回首页 | 更多教程