I Made Todoist 10x Smarter With an AI Layer on Top
I Made Todoist 10x Smarter With an AI Layer on Top
Last week I handed my agent a research task at 9am. At 11:14 I opened Todoist instead of the chat window.
There it was: the task sitting in π‘ In Progress, the agent's full plan in the description, four completed sub-steps logged as comments. I knew exactly where the work stood without scrolling through a single tool-call dump.
That's the whole trick. Your Todoist board becomes the face of your agent's work β and the agent keeps it updated automatically. Tasks get broken down, moved through states, and reported without you touching anything.
The problem: chat is a terrible status UI
If you run long agentic tasks, you know the failure mode.
You give the agent something big β "build a full-stack app," "do deep research on X." It disappears into its loop for an hour. What's it doing right now? You check the chat. You scroll. And scroll. The progress is in there somewhere, buried.
Checking chat logs manually is tedious, especially for background tasks. Skip the checking, and you get the worse failure mode: the agent stalled twenty minutes ago and you had no idea.
Here's the thing. Todoist power users already solved this problem for humans. Board, sections, comments, the satisfying drag from In Progress to Done. The board is a perfect status UI.
It's just missing an agent on the writing end. So give it one.
What the agent actually does
The setup (the guide calls it the todoist-task-manager pattern) makes your agent do four things on every complex task:
- Visualize state β create tasks in specific sections:
π‘ In Progress,π Waiting,π’ Done - Externalize reasoning β post its internal "Plan" into the task description
- Stream logs β add each sub-step completion as a comment in real time
- Auto-reconcile β a heartbeat script checks for stalled tasks and notifies you
That last one matters. "Stalled" is the state a chat window hides best. A task sitting in π Waiting with no new comments for an hour tells you instantly that something needs a human.
The setup: no skill to install
Here's my favorite part. There's no pre-built plugin. You prompt your agent to create the bash scripts itself, and since it manages its own filesystem and runs shell commands, it effectively builds the skill on request.
Step 1: Configure Todoist
Create a project (something like "Agent Workspace") and grab its project ID. Add three sections:
π‘ In Progressπ Waitingπ’ Done
You'll need the section IDs too β the Todoist REST API v2 docs show you how to list them.
Step 2: Three tiny scripts
scripts/todoist_api.sh β a thin curl wrapper around the REST API. Every other script goes through this:
#!/bin/bash
# Usage: ./todoist_api.sh <endpoint> <method> [data_json]
ENDPOINT=$1
METHOD=$2
DATA=$3
TOKEN="YOUR_TODOIST_API_TOKEN"
if [ -z "$DATA" ]; then
curl -s -X "$METHOD" "https://api.todoist.com/rest/v2/$ENDPOINT" \
-H "Authorization: Bearer $TOKEN"
else
curl -s -X "$METHOD" "https://api.todoist.com/rest/v2/$ENDPOINT" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d "$DATA"
fi
scripts/sync_task.sh β creates or updates tasks and routes them to the right section based on status. This is your state machine:
#!/bin/bash
# Usage: ./sync_task.sh <task_content> <status> [task_id] [description] [labels_json_array]
CONTENT=$1
STATUS=$2
TASK_ID=$3
DESCRIPTION=$4
LABELS=$5
PROJECT_ID="YOUR_PROJECT_ID"
case $STATUS in
"In Progress") SECTION_ID="SECTION_ID_PROGRESS" ;;
"Waiting") SECTION_ID="SECTION_ID_WAITING" ;;
"Done") SECTION_ID="SECTION_ID_DONE" ;;
*) SECTION_ID="" ;;
esac
PAYLOAD="{\"content\": \"$CONTENT\""
[ -n "$SECTION_ID" ] && PAYLOAD="$PAYLOAD, \"section_id\": \"$SECTION_ID\""
[ -n "$PROJECT_ID" ] && [ -z "$TASK_ID" ] && PAYLOAD="$PAYLOAD, \"project_id\": \"$PROJECT_ID\""
if [ -n "$DESCRIPTION" ]; then
ESC_DESC=$(echo "$DESCRIPTION" | sed ':a;N;$!ba;s/\n/\\n/g' | sed 's/"/\\"/g')
PAYLOAD="$PAYLOAD, \"description\": \"$ESC_DESC\""
fi
[ -n "$LABELS" ] && PAYLOAD="$PAYLOAD, \"labels\": $LABELS"
PAYLOAD="$PAYLOAD}"
if [ -n "$TASK_ID" ]; then
./scripts/todoist_api.sh "tasks/$TASK_ID" POST "$PAYLOAD"
else
./scripts/todoist_api.sh "tasks" POST "$PAYLOAD"
fi
scripts/add_comment.sh β the progress log. Every sub-step becomes a timestamped comment:
#!/bin/bash
# Usage: ./add_comment.sh <task_id> <comment_text>
TASK_ID=$1
TEXT=$2
ESC_TEXT=$(echo "$TEXT" | sed ':a;N;$!ba;s/\n/\\n/g' | sed 's/"/\\"/g')
PAYLOAD="{\"task_id\": \"$TASK_ID\", \"content\": \"$ESC_TEXT\"}"
./scripts/todoist_api.sh "comments" POST "$PAYLOAD"
Note the sed gymnastics in both scripts. That's load-bearing β multi-line descriptions and quote characters will break your JSON payload the first time they show up in a plan.
Step 3: The prompt that ties it together
Give your agent something like this:
I want you to build a Todoist-based task visibility system for your own runs.
First, create three bash scripts in a 'scripts/' folder:
1. todoist_api.sh (a curl wrapper for Todoist REST API)
2. sync_task.sh (create/update tasks with section_ids for In Progress, Waiting, Done)
3. add_comment.sh (post progress logs as comments)
Use these variables for the setup:
- Token: [Your Todoist API Token]
- Project ID: [Your Project ID]
- Section IDs: [In Progress ID, Waiting ID, Done ID]
Once created, for every complex task I give you:
1. Create a task in 'In Progress' with your full PLAN in the description.
2. For every sub-step completion, call add_comment.sh with a log of what you did.
3. Move the task to 'Done' when finished.
Step 4: The heartbeat
The fourth piece is a heartbeat script that checks for stalled tasks and notifies you. Same pattern: use the curl wrapper to list your In Progress tasks, check how long since each got its last comment, and ping you when one looks frozen. Run it on a cron every ten minutes or so. It's the difference between "the board is quiet" and "the board is stuck."
Why this beats building a dashboard
You could spin up a custom status dashboard. Don't.
The Todoist API is just REST and curl β no SDK, no webhooks, no websocket plumbing. Comments give you a timestamped log for free. Sections are a state machine you can literally see. The scripts even pass a labels JSON array, so you can filter agent tasks out of your personal views with Todoist's built-in filters.
And the mobile app becomes a free monitoring UI. Agent hits a blocker, moves the task to π Waiting, and it's on your phone.
Two gotchas from running this daily:
- Keep the agent's project separate. Don't mix it into your personal task lists. Clean lane, clean signal.
- Move the token out of the script if you're committing these anywhere.
TOKEN="$TODOIST_API_TOKEN"with an exported env var takes thirty seconds.
The honest version of "10x"
The multiplier isn't that the agent does your chores. It's that you stop babysitting it.
Trust comes from visibility, not vibes. When every plan is in a description and every step is a comment, you can walk away from a long-running task and come back to a board that tells the truth.
This recipe lives in the use case library at papayaclaw.com, alongside more agent-workflow setups like this one. Copy the prompt, hand it to your agent, and check your board in an hour.
