Task Relationships

Dodo supports two kinds of relationships between tasks: parent-child hierarchies and blocking dependencies.

Parent-Child

Organize tasks into a hierarchy. A task can have one parent and many children.

Creating subtasks

# Create a parent task
dodo add "Build auth system"

# Create children under it
dodo add "Implement login" --parent abc12345
dodo add "Implement signup" --parent abc12345
dodo add "Add password reset" --parent abc12345

Tree display

The list command renders parent-child relationships as a tree:

○ Build auth system                    [abc12345]
  └ ○ Implement login                  [def67890]
  └ ○ Implement signup                 [ghi11111]
  └ ○ Add password reset               [jkl22222]

Changing parents

# Set a parent
dodo update def67890 --parent abc12345

# Remove a parent (make it a root task)
dodo update def67890 --parent ""

Cycle detection

Dodo prevents circular parent-child relationships. If task A is a child of task B, you can't make task B a child of task A.

Blocking Dependencies

Model task dependencies where one task must be completed before another can proceed.

Adding blockers

# Create with blockers
dodo add "Deploy to production" --blocked-by abc12345,def67890

# Add a blocker to an existing task
dodo update jkl22222 --add-blocker abc12345

Automatic status management

When a task has blockers:

  • Its status is automatically set to blocked
  • When all blockers are completed (done), the status changes back to open
  • This happens automatically on complete and update commands
# Task B is blocked by Task A
dodo add "Task A"           # → open
dodo add "Task B" -b abc123 # → blocked

# Complete the blocker
dodo complete abc123         # Task A → done, Task B → open

Removing blockers

dodo update jkl22222 --remove-blocker abc12345

Cycle detection

Dodo prevents circular blocking dependencies. If task A blocks task B, you can't make task B block task A (even through intermediate tasks).

Cleanup on Delete

When a task is deleted, all references to it are cleaned up:

  • Its children become root tasks (parent is set to null)
  • It's removed from any blocked_by and blocks lists
  • Blocked tasks are re-evaluated and may become unblocked