4-page layout (Home, Recipes, Settings, Doctor) with sidebar nav and integrated Chat panel powered by OpenClaw agent (--local). - Home: status, agents overview, recommended recipes, recent activity - Recipes: browse, preview diff, apply with params - Settings: model profiles CRUD, chat model selection, provider catalog - Doctor: diagnostics with auto-fix - Chat: OpenClaw agent integration with session persistence, agent selector, read-only advisory context injection - Progressive data loading to avoid UI blocking - API key resolution from OpenClaw agent auth-profiles - Model catalog from openclaw CLI with cache Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
12 KiB
ClawPal MVP Implementation Plan
For Claude: REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.
Goal: Deliver a working Tauri MVP for ClawPal that implements install wizard, snapshot/rollback, and doctor repair flows with data-safe write operations.
Architecture: A thin React UI orchestrates a Rust-backed command API in Tauri; all configuration reads/writes, preview/rollback logic, and diagnosis checks are implemented in Rust for deterministic behavior and simpler cross-platform filesystem handling.
Tech Stack: Tauri 2, Rust, React 18, TypeScript, json5, monaco-editor (diff), Vitest, Cargo test
Task 1: 初始化项目骨架与基础命令骨架
Files:
- Create:
package.json - Create:
src-tauri/Cargo.toml - Create:
src-tauri/src/main.rs - Create:
src-tauri/src/commands.rs - Create:
src-tauri/src/lib.rs - Create:
src-tauri/src/commands_tests.rs - Create:
src/main.tsx - Create:
src/App.tsx - Create:
src-tauri/tauri.conf.json
Step 1: Write the failing test
Create a Rust compile smoke test for command registration entry.
// src-tauri/src/commands_tests.rs
#[test]
fn test_register_commands_compiles() {
assert!(true);
}
Step 2: Run it to verify it fails
Run: cd /Users/zhixian/Codes/clawpal/src-tauri && cargo test --test commands_tests -- --nocapture
Expected: FAIL with missing crate/modules (project尚未初始化).
Step 3: Write the minimal implementation
- Initialize a valid Tauri app with
invoke_handlerplaceholder. - Register placeholder command stubs returning
Ok(()).
Step 4: Run test to verify it passes
Run: cd /Users/zhixian/Codes/clawpal/src-tauri && cargo test --test commands_tests -- --nocapture
Expected: PASS.
Step 5: Commit
cd /Users/zhixian/Codes/clawpal
git add package.json src-tauri/Cargo.toml src-tauri/src/main.rs src-tauri/src/lib.rs src-tauri/src/commands.rs src-tauri/src/commands_tests.rs src-tauri/tauri.conf.json src/main.tsx src/App.tsx
git commit -m "chore: scaffold Tauri + React MVP project skeleton"
Task 2: 建立类型与路径模型
Files:
- Create:
src-tauri/src/models.rs - Create:
src-tauri/src/config_io.rs - Modify:
src-tauri/src/lib.rs - Create:
src-tauri/src/models_tests.rs
Step 1: Write the failing test
#[test]
fn test_openclaw_paths_are_resolved() {
let paths = resolve_openclaw_paths();
assert!(paths.config_path.to_string_lossy().contains(".openclaw"));
assert!(paths.history_dir.ends_with(".clawpal/history"));
}
Step 2: Run it to verify it fails
Run: cargo test models_tests::test_openclaw_paths_are_resolved
Expected: FAIL (path resolver未实现 / test compile fail).
Step 3: Write the minimal implementation
- Define
OpenClawPaths { config_path, history_dir, metadata_path }. - Implement path resolution from home directory via
dirscrate and create dirs if missing (non-destructive).
Step 4: Run test to verify it passes
Run: cargo test models_tests::test_openclaw_paths_are_resolved
Expected: PASS.
Step 5: Commit
git add src-tauri/src/models.rs src-tauri/src/config_io.rs src-tauri/src/models_tests.rs src-tauri/src/lib.rs
git commit -m "feat: define core path model for openclaw config and history"
Task 3: 实现 Recipe 类型与参数校验
Files:
- Create:
src-tauri/src/recipe.rs - Modify:
src-tauri/src/commands.rs - Create:
src/lib/recipe_catalog.ts - Create:
src-tauri/src/recipe_tests.rs
Step 1: Write the failing test
#[test]
fn test_validate_recipe_params_missing_required() {
let recipe = sample_recipe();
let params = serde_json::json!({});
assert!(validate_recipe_params(&recipe, ¶ms).is_err());
}
Step 2: Run it to verify it fails
Run: cargo test recipe_tests::test_validate_recipe_params_missing_required
Expected: FAIL (validate function未实现).
Step 3: Write the minimal implementation
- Implement
Recipe,RecipeParam,RecipeEngine::validate. - Parse params from static TS catalog entry and pass through Tauri command
list_recipes.
Step 4: Run test to verify it passes
Run: cargo test recipe_tests::test_validate_recipe_params_missing_required
Expected: PASS.
Step 5: Commit
git add src-tauri/src/recipe.rs src-tauri/src/recipe_tests.rs src-tauri/src/commands.rs src/lib/recipe_catalog.ts
git commit -m "feat: define recipe schema and parameter validation"
Task 4: 实现预览与应用流程(含备份)
Files:
- Modify:
src-tauri/src/recipe.rs - Modify:
src-tauri/src/config_io.rs - Create:
src-tauri/src/history.rs - Modify:
src-tauri/src/commands.rs - Create:
src-tauri/src/recipe_flow_tests.rs - Modify:
src/lib/api.ts - Create:
src/lib/types.ts
Step 1: Write the failing test
#[test]
fn test_apply_writes_backup_before_modify() {
// Arrange temp openclaw path & in-memory json
// Assert backup exists after apply with different content hash
}
Step 2: Run it to verify it fails
Run: cargo test recipe_flow_tests::test_apply_writes_backup_before_modify
Expected: FAIL (apply + history not implemented).
Step 3: Write the minimal implementation
- Implement preview by rendering template + merge patch to candidate JSON.
- On apply: read current config, create snapshot copy, write temporary file then atomically replace target.
- Emit
ApplyResultwithsnapshot_idand backup path.
Step 4: Run test to verify it passes
Run: cargo test recipe_flow_tests::test_apply_writes_backup_before_modify
Expected: PASS.
Step 5: Commit
git add src-tauri/src/recipe.rs src-tauri/src/config_io.rs src-tauri/src/history.rs src-tauri/src/commands.rs src-tauri/src/recipe_flow_tests.rs src/lib/api.ts src/lib/types.ts
git commit -m "feat: implement recipe preview/apply with backup snapshot"
Task 5: 实现历史列表和回滚命令
Files:
- Modify:
src-tauri/src/history.rs - Modify:
src-tauri/src/commands.rs - Create:
src-tauri/src/history_tests.rs - Create:
src/pages/History.tsx - Modify:
src/App.tsx
Step 1: Write the failing test
#[test]
fn test_history_snapshot_roundtrip_rollback() {
// create fake metadata + two snapshots
// restore earlier snapshot and verify current differs then matches target
}
Step 2: Run it to verify it fails
Run: cargo test history_tests::test_history_snapshot_roundtrip_rollback
Expected: FAIL (history index and rollback 未实现).
Step 3: Write the minimal implementation
- Implement metadata read/write format with monotonically sorted IDs.
- Implement
list_history,preview_rollback, androllback. - Add history UI with “查看 diff / 回滚” actions.
Step 4: Run test to verify it passes
Run: cargo test history_tests::test_history_snapshot_roundtrip_rollback
Expected: PASS.
Step 5: Commit
git add src-tauri/src/history.rs src-tauri/src/commands.rs src-tauri/src/history_tests.rs src/pages/History.tsx src/App.tsx
git commit -m "feat: add snapshot history list and rollback flow"
Task 6: 实现 Doctor 检查与修复
Files:
- Create:
src-tauri/src/doctor.rs - Modify:
src-tauri/src/commands.rs - Create:
src-tauri/src/doctor_tests.rs - Create:
src/pages/Doctor.tsx - Modify:
src/lib/api.ts
Step 1: Write the failing test
#[test]
fn test_doctor_catches_invalid_json_syntax() {
// Provide broken json5 content
// assert issue with code = json.syntax
}
Step 2: Run it to verify it fails
Run: cargo test doctor_tests::test_doctor_catches_invalid_json_syntax
Expected: FAIL (doctor module未实现).
Step 3: Write the minimal implementation
- Check parse validity, mandatory top-level fields, permission/ownership basics.
- Implement one-shot fix functions for trailing comma + missing required field default.
- Return actionable
DoctorReportfrom command.
Step 4: Run test to verify it passes
Run: cargo test doctor_tests::test_doctor_catches_invalid_json_syntax
Expected: PASS.
Step 5: Commit
git add src-tauri/src/doctor.rs src-tauri/src/commands.rs src-tauri/src/doctor_tests.rs src/pages/Doctor.tsx src/lib/api.ts
git commit -m "feat: add doctor diagnostics and safe auto-fix hooks"
Task 7: 前端安装向导与 Diff 页面
Files:
- Modify:
src/pages/Recipes.tsx - Create:
src/pages/Install.tsx - Create:
src/components/RecipeCard.tsx - Create:
src/components/ParamForm.tsx - Create:
src/components/DiffViewer.tsx - Modify:
src/lib/api.ts - Create:
src/pages/Home.tsx
Step 1: Write the failing test
// src/__tests__/InstallFlow.spec.ts
test('install flow shows preview and apply action', async () => {
render(<Install />);
// fill form -> click preview -> ensure diff rendered -> apply enabled
});
Step 2: Run it to verify it fails
Run: npx vitest run src/__tests__/InstallFlow.spec.ts
Expected: FAIL (页面未实现).
Step 3: Write the minimal implementation
- Wire form to Recipe params from catalog and invoke
preview_apply. - Add DiffViewer with highlight.
- Add confirm/apply button and success toasts.
Step 4: Run test to verify it passes
Run: npx vitest run src/__tests__/InstallFlow.spec.ts
Expected: PASS.
Step 5: Commit
git add src/pages/Recipes.tsx src/pages/Install.tsx src/components/RecipeCard.tsx src/components/ParamForm.tsx src/components/DiffViewer.tsx src/lib/api.ts src/pages/Home.tsx src/__tests__/InstallFlow.spec.ts
git commit -m "feat: implement recipe install wizard with preview+apply"
Task 8: 主页面路由与状态整合
Files:
- Modify:
src/App.tsx - Modify:
src/lib/state.ts - Modify:
src/pages/Home.tsx - Modify:
src/pages/History.tsx - Create:
src/lib/state_tests.ts
Step 1: Write the failing test
test('state loads recipes and history on boot', async () => {
// mock tauri commands, render App, assert key tiles are loaded
});
Step 2: Run it to verify it fails
Run: npx vitest run src/lib/state_tests.ts
Expected: FAIL (state orchestration未实现).
Step 3: Write the minimal implementation
- Implement shared reducer/events for system status, recipes, history, doctor report.
- Add tabs/routes for Home/Recipes/History/Doctor.
Step 4: Run test to verify it passes
Run: npx vitest run src/lib/state_tests.ts
Expected: PASS.
Step 5: Commit
git add src/App.tsx src/lib/state.ts src/lib/state_tests.ts src/pages/Home.tsx src/pages/History.tsx
git commit -m "feat: wire app-wide state and navigation"
Task 9: 端到端验收与发布脚手架
Files:
- Modify:
README.md - Modify:
package.json - Create:
scripts/release.sh - Create:
docs/mvp-checklist.md - Modify:
src-tauri/tauri.conf.json
Step 1: Write the failing test
./scripts/release.sh --dry-run
Expected: FAIL (脚本不存在).
Step 2: Run it to verify it fails
Run: bash scripts/release.sh --dry-run
Expected: FAIL / script not found.
Step 3: Write the minimal implementation
- Add build scripts and basic build verification matrix (macOS/Windows/Linux placeholders).
- Add manual QA checklist to validate install/rollback/doctor on clean and broken states.
- Update README for usage.
Step 4: Run test to verify it passes
Run: bash scripts/release.sh --dry-run
Expected: PASS (dry-run prints validated commands without publishing).
Step 5: Commit
git add README.md package.json scripts/release.sh docs/mvp-checklist.md src-tauri/tauri.conf.json
git commit -m "chore: add MVP runbook and release scripts"
执行方式
Plan complete and saved to docs/plans/2026-02-15-clawpal-mvp-implementation-plan.md. Two execution options:
- Subagent-Driven (this session) - 我在当前会话按任务分派并在每步进行复核
- Parallel Session (separate) - 开新会话并使用 executing-plans 执行,有里程碑检查点
Which approach?