One binary. Local‑first tasks in Markdown. Works great with agents.
This is a framework + scaffolding for a local-first task manager that stores tasks as Markdown files with YAML frontmatter, organized in a filesystem Kanban layout (projects + columns).
- Local‑first: tasks live as plain Markdown files.
- Agent‑friendly: human summaries by default, machine exports on demand.
- Simple: one binary, no database, easy backup with Git.
# after install
tasker init --project "Work"
tasker add "First task" --project Work --today
tasker tasks --project Work- Bootstrap OpenClaw (recommended):
openclaw onboard
# or
openclaw configureOpenClaw stores config at ~/.openclaw/openclaw.json by default (override with OPENCLAW_CONFIG_PATH).
The default workspace is ~/.openclaw/workspace.
- Install the CLI (pick one):
npm (recommended for non‑Go users)
npm install -g @amirbrooks/tasker-docstoreGo (recommended for Go users)
go install github.com/amirbrooks/tasker-docstore-framework/cmd/tasker@latest- Install the OpenClaw plugin (registers
tasker_cmd):
Copy extensions/tasker/ to one of:
<workspace>/.openclaw/extensions/tasker/~/.openclaw/extensions/tasker/
Or install via the CLI (copy or link):
openclaw plugins install ./extensions/tasker
openclaw plugins install -l ./extensions/tasker- Configure the OpenClaw plugin:
{
"plugins": {
"entries": {
"tasker": {
"enabled": true,
"config": {
"binary": "tasker",
"rootPath": "~/.tasker",
"timeoutMs": 15000,
"allowWrite": true
}
}
}
}
}- Allowlist the tool (required):
{
"agents": {
"list": [
{
"id": "main",
"tools": { "allow": ["tasker_cmd"] }
}
]
}
}- Install the unified skill to:
<workspace>/skills/task/(preferred)~/.openclaw/skills/task/
Skill:
- Unified skill:
skills/task/ - Optional helper:
./scripts/install-skill.sh --dest ~/.openclaw/skills
Full docs:
docs/OPENCLAW_INTEGRATION.mddocs/AGENT_WORKFLOW.mddocs/CLI_SPEC.mddocs/STORAGE_SPEC.mddocs/SECURITY.md
It is designed to integrate with OpenClaw via:
- a plugin tool (
tasker_cmd) that safely spawns thetaskerCLI withshell:false - a unified skill that maps natural language or
/tasktotasker_cmd
OpenClaw helpers:
TASKER_BIN=/path/to/tasker(env fallback if binary is not on PATH)./scripts/install-skill.sh --dest ~/.openclaw/skills
Explicit-only mode (optional):
{
"agent": {
"require_explicit": true
}
}Workflow setup (optional):
tasker workflow init
tasker workflow prompts init
tasker workflow schedule init --window 24h --heartbeat-every 2hWorkflow config lives at management/tasker/workflow.md in the OpenClaw workspace by default.
See Setup above for npm/Go install. Additional options:
Build from source
go build -o tasker ./cmd/taskerLocal install script
./scripts/install.sh- Initialize store (defaults to
~/.tasker):
tasker init --project "Work"Optional onboarding:
tasker onboardingView config (human summary):
tasker config showUpdate config (agent defaults):
tasker config set agent.default_project Work
tasker config set agent.default_view week
tasker config set agent.open_only true- Create another project (optional):
tasker project add "Side"- Add tasks:
tasker add "Draft proposal" --project Work --column todo --today --priority high --tag client
tasker add "Send recap" --project Work --tomorrow
tasker add "Plan next sprint" --project Work --next-week
tasker add "Fix auth bug" --project Work --column doing
tasker add --text "Draft proposal | outline scope | due 2026-01-23" --project Work
tasker capture "Quick note | due 2026-01-23"- Capture ideas (plain text):
tasker idea add "Draft onboarding flow"
tasker idea capture "Pricing experiment | explore enterprise tier | #pricing"
tasker idea capture "Prototype +Work @design"
cat notes.txt | tasker idea add --stdin
tasker idea note add "Draft onboarding flow" -- "share with design"
tasker idea promote "Pricing experiment" --project Work --column todo- List tasks:
tasker ls --project Work
tasker ls --project Work --json # writes JSON to <root>/exports- Due today + overdue:
tasker tasks --project Work- Board view:
tasker board --project Work --ascii- Week view:
tasker week --project Work --days 7Optional agent defaults (<root>/config.json):
{
"agent": {
"default_project": "work",
"default_view": "today",
"week_days": 7,
"open_only": true,
"require_explicit": false,
"summary_group": "project",
"summary_totals": true
}
}Set defaults to reduce flags:
TASKER_ROOT=/path/to/store(env) or--root <path>(flag)TASKER_PROJECT=work(env) oragent.default_project(config)TASKER_VIEW=week(env) oragent.default_view=week(config)TASKER_WEEK_DAYS=7(env) oragent.week_days=7(config)TASKER_OPEN_ONLY=true(env) oragent.open_only=true(config)TASKER_GROUP=project+TASKER_TOTALS=true(env) for grouped summaries
Output options:
- Human‑readable summaries by default
--plainfor stable tab‑separated output--json/--ndjsonwrite to<root>/exports(stdout JSON disabled by default)--asciifor board rendering--format telegramfor lean chat output (plain text)
Agent helpers:
tasker resolve "<selector>"returns JSON to stdout with matching IDs
Why use tasker instead of a plain Markdown list?
Tasker keeps tasks as Markdown but adds structured metadata (due/status/tags), deterministic views (today/week/board), and agent‑safe IDs without cluttering human output.
- Natural language: “tasks today for Work” →
tasker tasks --project Work - Natural language: “what’s our week looking like?” →
tasker week --project Work - Natural language: “capture Draft proposal | due 2026-01-23” →
tasker capture "Draft proposal | due 2026-01-23" - Onboarding:
tasker onboarding
JSON/NDJSON exports write to <root>/exports and are not printed to stdout unless --stdout-json or --stdout-ndjson is used.
Everything lives under a root folder (default: ~/.tasker):
.tasker/config.json(store config).tasker/projects/<project-slug>/project.json.tasker/projects/<project-slug>/columns/<column-dir>/*.md(tasks)
See docs/STORAGE_SPEC.md.
See docs/OPENCLAW_INTEGRATION.md.
See CONTRIBUTING.md.
See SECURITY.md and docs/SECURITY.md.
See SUPPORT.md.
- Tag a release (triggers GoReleaser):
git tag v0.1.0
git push origin v0.1.0- Publish npm wrapper (requires 2FA-enabled npm token):
cd npm
npm publish --access publicNotes:
- The npm wrapper downloads binaries from GitHub Releases, so the tag must exist before
npm publish.
MIT (see LICENSE).