TaskFlow
Structured project/task management for OpenClaw agents — markdown-first authoring, SQLite-backed querying, bidirectional sync, CLI, Apple Notes integration.
安装 / 下载方式
TotalClaw CLI推荐
totalclaw install skilldb:sm0ls~taskflowcURL直接下载,无需登录
curl -fsSL https://skills.taituai.com/api/skills/skilldb%3Asm0ls~taskflow/file -o taskflow.mdGit 仓库获取源码
git clone https://github.com/openclaw/skills/commit/125b68609968cef27d9006aa5cbce5f3b7d2acbe# TaskFlow — Agent Skill Reference
TaskFlow gives any OpenClaw agent a **structured project/task/plan system** with markdown-first authoring, SQLite-backed querying, and bidirectional sync.
**Principle:** Markdown is canonical. Edit `tasks/*.md` directly. The SQLite DB is a derived index, not the source of truth.
---
## Security
### OPENCLAW_WORKSPACE Trust Boundary
`OPENCLAW_WORKSPACE` is a **high-trust value**. All TaskFlow scripts resolve file paths from it, and the CLI and sync daemon use it to locate the SQLite database, markdown task files, and log directory.
**Rules for safe use:**
1. **Set it only from trusted, controlled sources.** The value must come from:
- Your own shell profile (`.zshrc`, `.bashrc`, `/etc/environment`)
- The systemd user unit `Environment=` directive in a template you control
- The macOS LaunchAgent `EnvironmentVariables` dictionary you installed
**Never** accept `OPENCLAW_WORKSPACE` from:
- User-supplied CLI arguments or HTTP request parameters
- Untrusted config files read at runtime
- Any external input that has not been explicitly validated
2. **Validate the path exists before use.** Any script that reads `OPENCLAW_WORKSPACE` should confirm the directory exists before proceeding:
```js
import { existsSync } from 'node:fs'
import path from 'node:path'
const workspace = process.env.OPENCLAW_WORKSPACE
if (!workspace) {
console.error('OPENCLAW_WORKSPACE is not set. Aborting.')
process.exit(1)
}
if (!existsSync(workspace)) {
console.error(`OPENCLAW_WORKSPACE path does not exist: ${workspace}`)
process.exit(1)
}
// Resolve to absolute path to neutralize any relative-path tricks
const safeWorkspace = path.resolve(workspace)
```
3. **Do not construct paths from untrusted input.** Even with a valid `OPENCLAW_WORKSPACE`, never concatenate unvalidated user input onto it (e.g. `path.join(workspace, userSlug, '../../../etc/passwd')`). Use `path.resolve()` and check that the resolved path starts with the workspace root:
```js
function safeJoin(base, ...parts) {
const resolved = path.resolve(base, ...parts)
if (!resolved.startsWith(path.resolve(base) + path.sep)) {
throw new Error(`Path traversal attempt detected: ${resolved}`)
}
return resolved
}
```
4. **Treat `OPENCLAW_WORKSPACE` as a local system path only.** It must point to a directory on the local filesystem. Remote paths (NFS mounts, network shares) may work but are outside the tested configuration and could introduce TOCTOU (time-of-check/time-of-use) race conditions.
---
## Setup
### 1. Set environment variable
Add to your shell profile (`.zshrc`, `.bashrc`, etc.):
```bash
export OPENCLAW_WORKSPACE="/path/to/your/.openclaw/workspace"
```
All TaskFlow scripts and the CLI resolve paths from this variable. Without it, they fall back to `process.cwd()`, which is almost never what you want.
> **See also:** [OPENCLAW_WORKSPACE Trust Boundary](#openclaw_workspace-trust-boundary) above for security requirements.
### 2. Link the CLI
```bash
ln -sf {baseDir}/scripts/taskflow-cli.mjs /opt/homebrew/bin/taskflow # macOS (Apple Silicon)
# or: ln -sf {baseDir}/scripts/taskflow-cli.mjs /usr/local/bin/taskflow
```
### 3. Run the setup wizard
```bash
taskflow setup
```
The wizard handles the rest: creates workspace directories, walks you through adding your first project(s), initializes the database, syncs, and optionally installs the macOS LaunchAgent for periodic sync.
**Alternative — manual setup:**
<details>
<summary>Manual steps (if you prefer explicit control)</summary>
```bash
# Create workspace dirs
mkdir -p "$OPENCLAW_WORKSPACE/tasks" "$OPENCLAW_WORKSPACE/plans" "$OPENCLAW_WORKSPACE/memory" "$OPENCLAW_WORKSPACE/logs"
# Bootstrap the DB schema
taskflow init
# Create PROJECTS.md and tasks/<slug>-tasks.md manually (see templates/)
# Sync markdown → DB
taskflow sync files-to-db
# Verify
taskflow status
```
</details>
---
## First Run
### For agents (OpenClaw / AI)
When a user asks you to set up TaskFlow or you detect it has not been initialized:
1. **Detect state.** Check for `$OPENCLAW_WORKSPACE/PROJECTS.md` and `$OPENCLAW_WORKSPACE/memory/taskflow.sqlite`.
2. **If clean slate:** Ask the user for their first project name and description, then run:
```bash
taskflow setup --name "Project Name" --desc "One-liner description"
```
Follow up by running `taskflow status` to confirm.
3. **If PROJECTS.md exists but no DB:** Run `taskflow setup` (it detects the state automatically and offers to init + sync).
4. **If both exist:** Run `taskflow status` — already set up.
5. After setup, update `AGENTS.md` with the new project slug so future sessions discover it via `cat PROJECTS.md`.
### For humans (CLI)
```bash
taskflow setup
```
The interactive wizard will:
- Detect your existing workspace state
- Walk you through naming your first project(s)
- Create `PROJECTS.md` and `tasks/<slug>-tasks.md` from templates
- Initialize the SQLite database and sync
- Offer to install the periodic-sync daemon (LaunchAgent on macOS, systemd timer on Linux) for automatic 60s sync
**Non-interactive (scripted installs):**
```bash
taskflow setup --name "My Project" --desc "What it does"
```
Passing `--name` skips all interactive prompts (daemon install is also skipped in non-interactive mode).
---
## Directory Layout
```
<workspace>/
├── PROJECTS.md # Project registry (one ## block per project)
├── tasks/<slug>-tasks.md # Task list per project
├── plans/<slug>-plan.md # Optional: architecture/design doc per project
└── taskflow/
├── SKILL.md # This file
├── scripts/
│ ├── taskflow-cli.mjs # CLI entry point (symlink target)
│ ├── task-sync.mjs # Bidirectional markdown ↔ SQLite sync
│ ├── init-db.mjs # Bootstrap SQLite schema (idempotent)
│ ├── export-projects-overview.mjs # JSON export of project/task state
│ └── apple-notes-export.mjs # Optional: project state → Apple Notes (macOS only)
├── templates/ # Starter files for new projects
├── schema/
│ └── taskflow.sql # Full DDL
└── system/
├── com.taskflow.sync.plist.xml # Periodic sync (macOS LaunchAgent)
├── taskflow-sync.service # Periodic sync (Linux systemd user unit)
└── taskflow-sync.timer # Systemd timer (60s interval)
<workspace>/
└── taskflow.config.json # Apple Notes config (auto-created on first notes run)
```
---
## Creating a Project
Follow this full checklist when creating a new project:
### 1. Add a block to `PROJECTS.md`
```markdown
## <slug>
- Name: <Human-Readable Name>
- Status: active
- Description: One-sentence description of the project.
```
- `slug` is lowercase, hyphenated (e.g., `my-project`). It becomes the canonical project ID everywhere.
- Valid status values: `active`, `paused`, `done`.
### 2. Create the task file
Copy `taskflow/templates/tasks-template.md` → `tasks/<slug>-tasks.md` and update the project name in the heading.
The file **must** contain these five section headers in this order:
```markdown
# <Project Name> — Tasks
## In Progress
## Pending Validation
## Backlog
## Blocked
## Done
```
### 3. Optionally create a plan file
Copy `taskflow/templates/plan-template.md` → `plans/<slug>-plan.md` for architecture docs, design decisions, and phased roadmaps. Plan files are **not** synced to SQLite — they are reference-only for the agent.
### 4. DB row (auto-created on first sync)
You do **not** need to manually insert into the `projects` table. The sync engine auto-creates the project row from `PROJECTS.md` on the next `files-to-db` run. If you want to be explicit via Node.js, use a parameterized statement:
```js
// Safe: parameterized insert — no string interpolation in the SQL
db.prepare(`INSERT INTO projec