Eddo Todo
Task management for the coding agent. Track todos, manage projects, log time.
Step 1: Set EDDO path (the CLI lives in this skill's directory):
# Inside Docker container:
EDDO="/home/agent/.pi/agent/skills/eddo-todo/eddo-todo.js"
# Or use environment variable if set:
EDDO="${PI_CODING_AGENT_DIR:-/home/agent/.pi/agent}/skills/eddo-todo/eddo-todo.js"
Step 2: Build METADATA (extract values from <pi_session_metadata> in your context):
BRANCH=$(git branch --show-current 2>/dev/null || echo "none")
METADATA='{"agent:session":"YOUR_PI_SESSION_ID","agent:model":"YOUR_PI_MODEL","agent:cwd":"YOUR_PI_CWD","agent:branch":"'$BRANCH'"}'
Replace YOUR_PI_SESSION_ID, YOUR_PI_MODEL, YOUR_PI_CWD with actual values from <pi_session_metadata>.
Step 3: Use the variables:
$EDDO next
$EDDO get <id>
$EDDO create "Task" -c context -t gtd:next -M "$METADATA" -D "task description" -m "why creating this"
⚠️ DO NOT look for eddo.js in the current working directory - it's in the skill directory.
⚠️ DO NOT use placeholder text like <PI_SESSION_ID> literally - substitute actual values.
Related Skills
- eddo-work: Structured phases for implementing complex tasks (REFINE → IMPLEMENT → REVIEW → COMPLETE → GITHUB_PR)
Setup
Prerequisite: Eddo MCP server accessible from container (via Docker network)
# Inside Docker container:
EDDO="/home/agent/.pi/agent/skills/eddo-todo/eddo-todo.js"
# The MCP URL should be set via environment variable by the container orchestrator
# Default: http://host.docker.internal:3001/mcp (to reach host's MCP server)
export EDDO_MCP_URL=${EDDO_MCP_URL:-http://host.docker.internal:3001/mcp}
# MCP API key (stored in user preferences)
export EDDO_MCP_API_KEY=${EDDO_MCP_API_KEY:-""}
Short Flags
ALWAYS use short flags - saves tokens:
| Short | Long | Short | Long |
|---|---|---|---|
-c |
--context |
-t |
--tag |
-d |
--due |
-m |
--message |
-D |
--description |
-l |
--link |
-e |
--external-id |
-E |
--clear-external-id |
-p |
--parent-id |
-P |
--clear-parent |
-b |
--blocked-by |
-B |
--clear-blockers |
-M |
--metadata |
-u |
--undo |
ALWAYS use -D for task description (what), -m for audit message (why), and -M for metadata on create.
Commands
next - GTD Candidates
$EDDO next # Show actionable candidates
$EDDO next --context eddoapp # Candidates for specific project
Priority groups: ⚠️ OVERDUE → 🚀 NEXT ACTIONS → 📅 DUE SOON → 📋 PROJECTS → 📝 OTHER
list - Filter todos
$EDDO list # All todos
$EDDO list --context eddoapp # Filter by project
$EDDO list --completed # Show completed
$EDDO list --tag gtd:next # Next actions only
get - Full details
$EDDO get <id>
create - New todo
$EDDO create "Fix bug" -c work -t gtd:next -M "$METADATA" -D "Login fails on Safari when cookies disabled" -m "Found during QA testing"
$EDDO create "Subtask" -c work -t gtd:next -p "parent-id" -M "$METADATA" -D "Implement JWT refresh logic" -m "Breaking down auth project"
$EDDO create "Issue #42" -c work -t gtd:next \
-l "https://github.com/owner/repo/issues/42" \
-e "github:owner/repo/issues/42" -M "$METADATA" -D "User reports crash on startup" -m "Imported from GitHub"
update - Modify todo
$EDDO update <id> --title "New title"
$EDDO update <id> --due 2025-01-15 -m "Pushed to next week"
$EDDO update <id> -p "new-parent" # Set parent
$EDDO update <id> -P # Clear parent (make root-level)
$EDDO update <id> -B # Clear blockers
$EDDO update <id> -E # Clear external ID
$EDDO update <id> --clear-metadata # Clear metadata
children - List subtasks
$EDDO children <parent-id>
complete - Mark done
$EDDO complete <id> -m "Fixed the bug"
$EDDO complete <id> --undo # Uncomplete
delete - Remove todo
$EDDO delete <id>
notes - Work diary
$EDDO note <id> "Note content" # Add note
$EDDO notes <id> # List notes
$EDDO note-delete <id> <note-id> # Delete note
Worth noting: Discoveries, decisions + reasoning, surprises, blockers, gotchas, insights. NOT worth noting: "Started X", "Completed Y" (tracked elsewhere).
attachments - File attachments
$EDDO attach <id> /path/to/file.png # Attach file to todo
$EDDO attach <id> /path/to/file.png --name chart.png # Override filename
$EDDO attachments <id> # List attachments
$EDDO get-attachment <docId> --output /tmp/img.png # Download attachment
$EDDO get-attachment <docId> --base64 # Output base64 to stdout
Uploads file to attachments database and appends markdown reference to todo description. Supported types: PNG, JPEG, GIF, WebP, PDF (max 5MB).
To read an image from a todo, first list attachments to get the docId, then download it.
Time tracking
$EDDO start <id> -M "$METADATA" -m "Beginning work" # Start with metadata
$EDDO stop <id> -m "Pausing"
$EDDO active # Show active tracking
info - Server status
$EDDO info
GTD System
Tags (actionability):
| Tag | When to Use |
|---|---|
gtd:next |
Ready to execute, no blockers |
gtd:project |
Multi-step outcome |
gtd:waiting |
Blocked on external input (person, event) |
gtd:blocked |
Blocked on internal task (use with --blocked-by) |
gtd:someday |
Not committed, future possibility |
gtd:calendar |
Time-specific (prefix title with HH:MM) |
Contexts (where/when):
| Context | When to Use |
|---|---|
owner/repo |
GitHub repo slug (e.g., walterra/eddoapp) |
inbox |
Uncategorized (default) |
private |
Personal non-work |
errands |
Physical location tasks |
Derive context from git:
git remote get-url origin 2>/dev/null | sed 's/.*[:/]\([^/]*\/[^/]*\)\.git$/\1/' | sed 's/.*[:/]\([^/]*\/[^/]*\)$/\1/'
GitHub Integration
Link todos to GitHub issues for auto-completion when issue closes.
External ID format: github:owner/repo/issues/NUMBER
REPO=$(git remote get-url origin 2>/dev/null | sed 's/.*[:/]\([^/]*\/[^/]*\)\.git$/\1/' | sed 's/.*[:/]\([^/]*\/[^/]*\)$/\1/')
ISSUE_NUMBER=42
$EDDO update <id> \
--link "https://github.com/$REPO/issues/$ISSUE_NUMBER" \
--external-id "github:$REPO/issues/$ISSUE_NUMBER"
⚠️ NEVER manually complete todos with externalId - let GitHub sync handle it!
Parent-Child Relationships
# Create parent
$EDDO create "Build auth system" -c eddoapp -t gtd:project -M "$METADATA" -D "OAuth2 + JWT authentication" -m "New feature request"
# Create subtasks (use parent's ID)
$EDDO create "Design login" -c eddoapp -t gtd:next -p "parent-id" -M "$METADATA" -D "Figma mockups for login flow" -m "Breaking down project"
$EDDO create "Implement JWT" -c eddoapp -p "parent-id" -M "$METADATA" -D "Backend token generation and validation" -m "Breaking down project"
# View subtasks
$EDDO children <parent-id>
Task Dependencies (blockedBy)
Use gtd:blocked tag with -b to track internal task dependencies.
# Mark task B as blocked by task A
$EDDO update <B> -t gtd:blocked -b <A> -m "Blocked by task A"
# Multiple blockers (repeatable flag)
$EDDO update <B> -t gtd:blocked -b <A1> -b <A2> -m "Blocked by A1 and A2"
# Clear all blockers
$EDDO update <B> -B -t gtd:next -m "Unblocked"
Behavior:
- Tasks with
gtd:blockedtag or incompleteblockedByreferences are excluded fromnext - Distinct from
gtd:waitingwhich is for external blocks (people, events) - Supports cross-project dependencies (not just parent-child)
Metadata
⚠️ MANDATORY: ALWAYS include -M metadata on EVERY create command.
Required fields (from <pi_session_metadata>):
| Field | Source |
|---|---|
agent:session |
PI_SESSION_ID |
agent:model |
PI_MODEL |
agent:cwd |
PI_CWD |
agent:branch |
git branch --show-current |
$EDDO create "Task" -c ctx -t gtd:next -M "$METADATA" -D "What the task is about" -m "Why creating it"
Examples
# Quick task management
$EDDO create "Fix login bug" -c work -t gtd:next -M "$METADATA" -D "Login fails on Safari when cookies disabled" -m "User reported in support ticket #123"
$EDDO create "Learn Rust" -c private -t gtd:someday -M "$METADATA" -D "Work through the Rust book, build a CLI tool" -m "Adding to someday list"
# Simple time tracking
$EDDO next # Get next action
$EDDO start <id> -M "$METADATA" -m "Starting work on this"
# ... work ...
$EDDO stop <id> -m "Pausing for lunch"
$EDDO complete <id> -m "Fixed by clearing stale cookies"
Converted and distributed by TomeVault — claim your Tome and manage your conversions.