Guide

Yes! Did It is a CLI-first todo tracker designed for developers. Capture tasks from your terminal or AI assistant, query them, and mark them done — without leaving your workflow.

Core Concepts

  • CLI-first — all mutations (add, complete, update) happen via the CLI or API. The web dashboard is for viewing and deleting.
  • MCP-ready — Claude can manage your todos through the MCP server integration.
  • Time filters — query todos by time: today, tomorrow, this-week, overdue, upcoming, next-hour.
  • Tags — organize todos with tags for grouping and filtering.

CLI Commands

Adding Todos

ydi add "Ship the API" --due "today 5pm"
ydi add "Review PR" --due "tomorrow 10am" --tag work --tag review
ydi add "Buy groceries"

Due dates support natural language. Tags are comma-separated.

Listing Todos

ydi list                          # All pending todos
ydi list --filter today           # Due today
ydi list --filter overdue         # Past due
ydi list --filter this-week       # Due this week
ydi list --all                    # Include completed
ydi list --tag work               # Filter by tag
ydi list --current-branch         # Todos on current git branch
ydi list --branch feat/auth       # Todos on a specific branch
ydi list --here                   # Todos in current repo
ydi list --active                 # Todos on branches with recent commits
ydi list --verbose                # Show full git context

Updating Todos

ydi update abc123 --text "New text"   # Change text
ydi update abc123 --due "friday 5pm"  # Change due date
ydi update abc123 --clear-due         # Remove due date
ydi update abc123 --tag work --tag v2 # Replace tags
ydi update abc123 --clear-tags        # Remove all tags
ydi update                            # Interactive picker

Combine multiple flags in one command to update several fields at once.

Completing Todos

ydi done abc123                   # By ID (short prefix works)
ydi done                          # Interactive picker

When you run ydi done without an ID, an interactive picker lets you search and select from your pending todos.

Deleting Todos

ydi delete abc123                 # By ID
ydi delete                        # Interactive picker

Managing API Keys

ydi keys create --name "CI"       # Generate a new key
ydi keys list                     # List active keys

Git Context

When you create a todo inside a git repository, the CLI automatically captures the current branch, commit SHA, and repository URL. This context links your todos to the code you're working on.

ydi add "Fix auth token refresh"
# Added: abc123  [feat/auth-fix]

ydi context                    # See what would be captured
# Branch:  feat/auth-fix
# Commit:  a1b2c3d
# Repo:    https://github.com/you/project.git
# Slug:    you/project

ydi add "Unrelated task" --no-context   # Skip capture

Context powers branch-based filtering (ydi list --current-branch), verbose display (-v), stale todo detection, and more.

Stale Todo Detection

When a branch is deleted (usually after a PR merge), its todos become stale. The sweep command finds and cleans them up:

ydi sweep                # Interactive — select which stale todos to complete
ydi sweep --dry-run      # Preview stale todos without acting
ydi sweep --auto         # Mark all stale todos as done
ydi list --stale         # List stale todos without completing them

A todo is considered stale when its branch no longer exists on the remote (i.e., the branch was deleted after a PR merge). Local-only branches are not considered stale.

Standup Reports

Generate a standup report showing recently completed todos grouped by branch, plus your current in-progress work:

ydi standup                      # Last 24 hours (default)
ydi standup --since "yesterday 9am"  # Custom lookback
ydi standup --since 48h          # Duration format
ydi standup --json               # Structured output

Configuration

Customize CLI behavior with persistent settings stored in ~/.config/yesdidit/settings.json:

ydi config list                  # Show all settings
ydi config set context.auto false  # Disable auto git context
ydi config set default_filter today  # Default list filter
ydi config set standup.since 48h   # Default standup lookback
ydi config get verbose           # Check a setting

Using with Claude (MCP)

Once the MCP server is configured, you can ask Claude to manage your todos conversationally:

  • "Add a todo to deploy the staging server by Friday"
  • "What's due today?"
  • "What todos are on this branch?"
  • "Give me a standup report"
  • "Are there any stale todos to clean up?"
  • "Mark the deploy todo as done"
  • "Show me everything tagged 'urgent'"
  • "Delete the grocery todo"

API Overview

The full API is available at https://api.yesdidit.com/api. Authenticate with a Bearer JWT or API key.

# List todos due today
curl -H "Authorization: ApiKey ydi_live_..." \
  "https://api.yesdidit.com/api/todos?filter=today"

# Create a todo
curl -X POST \
  -H "Authorization: ApiKey ydi_live_..." \
  -H "Content-Type: application/json" \
  -d '{"text": "Deploy v2", "due_at": "2026-03-23T17:00:00Z"}' \
  https://api.yesdidit.com/api/todos

# Mark complete
curl -X POST \
  -H "Authorization: ApiKey ydi_live_..." \
  https://api.yesdidit.com/api/todos/ID/done

For the complete API specification, see the GitHub repository.

Scripting & Automation

Every ydi command supports --json for machine-readable output, making it easy to chain with other tools in shell scripts. Use an API key for headless environments where interactive login isn't possible.

Piping & Filtering

# Print just the text of today's todos
ydi list --filter today --json | jq -r '.[].text'

# Count overdue items
ydi list --filter overdue --json | jq length

# Get IDs of todos tagged "release"
ydi list --tag release --json | jq -r '.[].id'

Bulk Operations

# Add multiple todos from a file (one per line)
while IFS= read -r line; do
  ydi add "$line" --tag sprint
done < backlog.txt

# Mark all overdue todos as done
ydi list --filter overdue --json \
  | jq -r '.[].id' \
  | xargs -I{} ydi done {}

CI / Deploy Gates

# Fail a CI build if release todos are still open
export YDI_API_KEY="ydi_live_..."
open_count=$(ydi list --tag release --json | jq length)
if [ "$open_count" -gt 0 ]; then
  echo "❌ $open_count release todo(s) still open"
  ydi list --tag release
  exit 1
fi

# Log a deploy as a completed todo
ydi add "Deploy v$VERSION to prod" --tag deploy
ydi done $(ydi list --tag deploy --json | jq -r '.[-1].id')

Cron & Notifications

# Daily digest via cron (add to crontab)
# 0 9 * * * /path/to/daily-digest.sh

#!/bin/bash
todos=$(ydi list --filter today --json)
count=$(echo "$todos" | jq length)
if [ "$count" -gt 0 ]; then
  echo "$count todo(s) due today:" | mail -s "YDI Daily Digest" you@example.com
  echo "$todos" | jq -r '.[].text' | mail -s "YDI Daily Digest" you@example.com
fi

Troubleshooting

Token expired

The CLI automatically refreshes tokens. If you see auth errors, run ydi login to re-authenticate.

API unreachable

For local development, make sure the API server is running (pnpm turbo dev). To point the CLI at a local API:

YDI_API_URL=http://localhost:3000 ydi list

MCP not responding

Ensure you're signed in via the CLI first (ydi login). The MCP server reads credentials from the same config file.