todolist-loop
v0.1.0
Published
Task-driven auto-execution loop plugin for OpenCode
Maintainers
Readme
todolist-loop
Task-driven auto-execution loop plugin for OpenCode
Define a task graph in target.yaml, and todolist-loop automatically orchestrates subagents to execute each node — with dependency resolution, retry logic, and completion verification.
Features
- DAG-based task orchestration — Define tasks and dependencies in YAML
- Automatic subagent dispatch — Orchestrator assigns Executor, Review, and Root Cause subagents
- Dependency resolution — Hard/soft edges with data/interface/sequence categories
- Built-in retry logic — 3 retries per node before escalation to root-cause analysis
- Two-stage review — Light Review (checklist + files + commands) + Deep Review (critical issue scan)
- Model overrides — Per-role and per-node model configuration
- Handoff context — Upstream node summaries passed to downstream nodes
- Constraints system — Global and per-node constraints injected into agent prompts
- ASCII DAG preview — Visual task graph rendering with status icons
- Auto-discover — Find graph.yaml without specifying file path
- SKILL.md injection — Auto-inject project workflow guidance
- AI graph builder — Generate task graphs from project files
- Stall detection — Auto-repair with configurable rounds
- Zero external dependencies — Bundled with esbuild, no node_modules needed at runtime
Installation
# Clone the repository
git clone <repo-url>
cd todolist-loop
# Install dev dependencies
npm install
# Build
npm run buildAs an OpenCode Plugin
Add to your OpenCode configuration (opencode.json or equivalent):
{
"plugins": {
"todolist-loop": {
"path": "/path/to/todolist-loop"
}
}
}Quick Start
- Write a target.yaml in your project root:
goal:
description: "Set up a new web project"
graph:
nodes:
setup:
name: "Project Setup"
description: "Initialize project structure"
gate:
checklist:
- "package.json exists"
- "Dependencies installed"
build:
name: "Build"
description: "Build the project"
gate:
checklist:
- "Build succeeds"
command: "npm run build"
edges:
- from: setup
to: build
type: hard
category: sequence- Start the loop in your OpenCode session:
/todolist-loopIf no file is specified, the plugin auto-discovers the graph file in this order:
.todolist-loop/graph.yaml→graph.yaml→target.yamlYou can still pass a file explicitly:
/todolist-loop target.yaml
- Watch it go — the plugin will automatically orchestrate subagents to complete each task.
Commands
| Command | Description |
|---------|-------------|
| /todolist-loop [file] | Start a new task loop (auto-discovers graph.yaml) |
| /loop-status | Show current loop progress |
| /pause-loop | Pause the loop (chat freely while paused) |
| /resume-loop | Resume from pause point |
| /cancel-loop | Cancel current loop |
| /todolist-loop-build <file> | Generate a task graph from a source file using AI |
| /loop-cleanup | Force clean up all loop state files |
target.yaml Format
goal:
description: string # Overall goal
sources: # Optional: source files to analyze
- file: string
graph:
constraints: [string] # Optional: global constraints injected into all prompts
nodes:
<node-id>: # Unique kebab-case identifier
name: string # Human-readable name
description: string # What to accomplish
constraints: [string] # Optional: per-node constraints
skills: [string] # Optional: recommended skills
model_override: # Optional: per-node model
provider: string
model: string
gate:
checklist: [string] # Completion criteria
files_exist: [string] # Expected output files
command: string # Verification command
edges:
- from: string
to: string
type: "hard"|"soft" # hard=cascade skip, soft=fallback
category: "data"|"interface"|"sequence"
model_overrides: # Optional: global per-role overrides
executor:
provider: string
model: stringDependency Types
- hard: If upstream is SKIPPED, downstream is auto-SKIPPED
- soft: If upstream is SKIPPED, use fallback or skip gracefully
Categories
- data: Needs upstream's output data
- interface: Needs upstream's API/interface ready
- sequence: Just needs upstream to run first
Configuration
Model Overrides
Control which AI model each subagent uses:
# Global override (all executors use this model)
model_overrides:
executor:
provider: "anthropic"
model: "claude-sonnet"
# Per-node override (overrides global for this node)
graph:
nodes:
code-review:
name: "Code Review"
model_override:
provider: "openai"
model: "gpt-4"Resolution priority: Node-level > Global > Plugin default > Main session model
Custom Templates
Override the continuation prompt by creating .todolist-loop/templates/continuation.md. The default template uses Mustache-like syntax ({{variable}}, {{#section}}...{{/section}}).
Timeout Settings
Default subagent timeout is 600 seconds (10 minutes). Configure via state:
subagent_timeout_ms: 300000 # 5 minutesConstraints
Constraints let you attach project-specific rules that are automatically injected into every continuation prompt. Define them at the graph level (apply to all nodes) or at the node level (apply to a single node).
graph:
constraints:
- "Use TypeScript strict mode (tsconfig.json:1-10)"
- "Follow conventional commits (commitlint.config.js:1-5)"
nodes:
code-review:
name: "Code Review"
constraints:
- "Only review files in src/ directory"Both graph-level and node-level constraints are merged and included in the agent's continuation prompt before execution.
SKILL.md Injection
If a SKILL.md file exists at the project root (or .todolist-loop/SKILL.md), its contents are automatically read and injected into the continuation prompt at loop start. This lets you provide project-specific workflow guidance without modifying templates.
ASCII DAG Preview
The graph builder CLI can render an ASCII visualization of the task graph:
npm run graph -- render target.yaml --asciiStatus icons used in the preview:
| Icon | Status | |------|--------| | ⬜ | NEW — Not yet started | | 🔄 | WIP — Work in progress | | ✅ | DONE — Completed successfully | | ⏭️ | SKIP — Skipped (upstream failed or marked skip) | | ❌ | FAIL — Failed (retries exhausted) |
Example output:
[Task Graph] setup → build → test → deploy
setup ⬜ NEW Project Setup
│
▼ (hard/sequence)
build ⬜ NEW Build
│
▼ (hard/sequence)
test ⬜ NEW Run Tests
│
├──▶ lint ⬜ NEW ESLint (soft/data)
│
▼ (hard/sequence)
deploy ⬜ NEW DeployWhen running /todolist-loop-build, an ASCII DAG preview is automatically generated as part of the output.
Architecture
┌─────────────────────────────────────────────┐
│ OpenCode │
│ │
│ ┌─────────┐ ┌──────────────────────┐ │
│ │ Plugin │───▶│ Continuation Builder │ │
│ │ Server │ │ ├─ Template │ │
│ │ │ │ ├─ Model Overrides │ │
│ │ Hooks: │ │ └─ Upstream Context │ │
│ │ - event │ └──────────────────────┘ │
│ │ - cmd │ │ │
│ │ - msg │ ▼ │
│ └─────────┘ ┌──────────────────────┐ │
│ │ State Engine │ │
│ │ ├─ Loop State │ │
│ │ ├─ Node State │ │
│ │ └─ Graph Manager │ │
│ └──────────────────────┘ │
│ │ │
│ ▼ │
│ ┌──────────────────────┐ │
│ │ Orchestrator Agent │ │
│ │ ├─ Executor Agent │ │
│ │ ├─ Review Agent │ │
│ │ └─ Root Cause Agent │ │
│ └──────────────────────┘ │
└─────────────────────────────────────────────┘Key Modules
| Module | Responsibility |
|--------|---------------|
| src/index.ts | Plugin entry point, hook registration |
| src/prompt/continuation-builder.ts | Build continuation prompts with model + handoff data |
| src/state/state-engine.ts | State persistence and node management |
| src/state/graph-manager.ts | DAG operations (read/write/ready nodes) |
| src/hooks/loop-hook.ts | Main loop logic (idle handler, completion, retry) |
| src/config/model-resolver.ts | Three-layer model resolution |
| src/scripts/graph-builder.ts | CLI graph builder with constraints extraction and ASCII preview |
| src/utils/ascii-renderer.ts | ASCII DAG visualization with status rendering |
Development
# Install dependencies
npm install
# Build
npm run build
# Run unit tests
npm test
# Run E2E tests (requires OpenCode SDK)
npm run test:e2e
# Graph builder CLI
npm run graph -- validate target.yamlTest Architecture
- Unit tests:
src/**/*.test.ts— Vitest, fast, no external deps - E2E tests:
tests/e2e/real-e2e.test.ts— Direct Import pattern, tests plugin hooks directly - SDK E2E tests:
tests/e2e/real-e2e.test.ts— Full OpenCode SDK, real server (needsRUN_REAL_E2E=1)
License
MIT — See LICENSE
