← Back to Kontasks
Todo Progress Tracking in Kontasks
Analysis of how to persist Claude's todo state in kontasks for crash recovery
Output
Todo Progress Tracking for Crash Recovery
The Problem
When konsole restarts or client disconnects, the todo state (what Claude was working on, what's completed) is lost. The current recovery relies on:
workingHistory- tool calls streamed to clientrequestIdmatching - finding the kontask by requestkontexts- stored after completion only
Gap: Mid-flight todo state isn't persisted anywhere recoverable.
Current Architecture
Dashboard ──SSE──► Konui ──HTTP──► Konsole ──spawn──► Claude │ │ └── localStorage └── workingHistory (in-memory) • pending prompt • tool_use events • requestId • kontexts (saved after done) • deleted IDs
Proposed Solution: Live Kontask Updates
Store todo state inside the kontask context as Claude works, not just at completion.
Option A: Incremental Kontask Updates
// Konsole watches for TodoWrite tool calls
// Updates kontask.context.todos in real-time
kontask.context = {
output: "<div>...</div>",
requestId: "abc123",
todos: [
{ content: "Fix X", status: "completed" },
{ content: "Update Y", status: "in_progress" },
{ content: "Test Z", status: "pending" }
],
lastTodoUpdate: "2026-01-02T08:45:00Z"
}
Option B: Separate Progress Kontask
// Create a "progress" kontask type that's auto-updated
// Client polls/subscribes for progress updates
{
type: "progress",
title: "Working: Fix authentication bug",
context: {
parentRequestId: "abc123",
todos: [...],
workingHistory: [...],
startedAt: "...",
lastActivity: "..."
}
}
Implementation Points
| Component | Change |
|---|---|
konsole/stream.ts |
Detect TodoWrite calls, update kontask via MCP |
konui/kontask-db.ts |
Add updateKontaskTodos() method |
dashboard-console.ts |
Render todos from recovered kontask |
konui/router.ts |
API endpoint to get progress by requestId |
Recovery Flow (After Change)
1. Client reconnects 2. Loads pendingRequestId from localStorage 3. Fetches kontask by requestId 4. If kontask has context.todos: → Render todo list showing progress → Show "Claude was working on: {activeForm}" 5. If kontask has output: → Display completed output card
Key Insight: The kontask already has requestId for matching. Adding context.todos and updating it during streaming gives us persistent todo state without new storage.
Quick Actions
Original Request
No layout configured
Details
Type
General
Status
Completed
Scope
vibetools
Tags
kontaskstodosrecoverykonsole
Created
2 Jan 2026, 12:10 pm
Updated
2 Jan 2026, 12:10 pm
Created By
claude
📋 Claude's Context
Working On
Analyzing todo persistence options for kontask crash recovery
Session
dashboard...
Raw Data
{
"id": "797af873-c2e6-4a61-9e56-3c8b442af44f",
"type": "general",
"status": "completed",
"title": "Todo Progress Tracking in Kontasks",
"description": "Analysis of how to persist Claude's todo state in kontasks for crash recovery",
"context": {
"output": "<div style=\"background:#1e1e1e;color:#e0e0e0;padding:20px;border-radius:8px;font-family:sans-serif;\">\n<h2 style=\"color:#fff;margin:0 0 16px 0;\">Todo Progress Tracking for Crash Recovery</h2>\n\n<div style=\"background:#2d2d2d;padding:16px;border-radius:6px;margin-bottom:16px;\">\n<h3 style=\"color:#f44336;margin:0 0 12px 0;\">The Problem</h3>\n<p style=\"margin:0;line-height:1.6;\">When konsole restarts or client disconnects, the todo state (what Claude was working on, what's completed) is lost. The current recovery relies on:</p>\n<ul style=\"margin:12px 0 0 0;padding-left:20px;line-height:1.8;\">\n<li><code style=\"background:#3d3d3d;padding:2px 6px;border-radius:3px;\">workingHistory</code> - tool calls streamed to client</li>\n<li><code style=\"background:#3d3d3d;padding:2px 6px;border-radius:3px;\">requestId</code> matching - finding the kontask by request</li>\n<li><code style=\"background:#3d3d3d;padding:2px 6px;border-radius:3px;\">kontexts</code> - stored after completion only</li>\n</ul>\n<p style=\"margin:12px 0 0 0;color:#ff9800;\">Gap: Mid-flight todo state isn't persisted anywhere recoverable.</p>\n</div>\n\n<div style=\"background:#2d2d2d;padding:16px;border-radius:6px;margin-bottom:16px;\">\n<h3 style=\"color:#4caf50;margin:0 0 12px 0;\">Current Architecture</h3>\n<pre style=\"background:#1e1e1e;padding:12px;border-radius:4px;font-family:monospace;font-size:0.85rem;overflow-x:auto;line-height:1.6;\">\n<span style=\"color:#61afef;\">Dashboard</span> ──SSE──► <span style=\"color:#98c379;\">Konui</span> ──HTTP──► <span style=\"color:#e5c07b;\">Konsole</span> ──spawn──► <span style=\"color:#c678dd;\">Claude</span>\n │ │\n └── localStorage └── <span style=\"color:#7f848e;\">workingHistory (in-memory)</span>\n • pending prompt • tool_use events\n • requestId • kontexts (saved after done)\n • deleted IDs\n</pre>\n</div>\n\n<div style=\"background:#2d2d2d;padding:16px;border-radius:6px;margin-bottom:16px;\">\n<h3 style=\"color:#2196f3;margin:0 0 12px 0;\">Proposed Solution: Live Kontask Updates</h3>\n<p style=\"margin:0 0 12px 0;line-height:1.6;\">Store todo state <strong>inside the kontask context</strong> as Claude works, not just at completion.</p>\n\n<div style=\"background:#1e1e1e;padding:12px;border-radius:4px;margin:12px 0;\">\n<p style=\"margin:0 0 8px 0;color:#98c379;font-weight:bold;\">Option A: Incremental Kontask Updates</p>\n<pre style=\"font-family:monospace;font-size:0.85rem;margin:0;line-height:1.5;\">\n// Konsole watches for TodoWrite tool calls\n// Updates kontask.context.todos in real-time\n\nkontask.context = {\n output: \"<div>...</div>\",\n requestId: \"abc123\",\n <span style=\"color:#98c379;\">todos: [</span>\n <span style=\"color:#98c379;\">{ content: \"Fix X\", status: \"completed\" },</span>\n <span style=\"color:#98c379;\">{ content: \"Update Y\", status: \"in_progress\" },</span>\n <span style=\"color:#98c379;\">{ content: \"Test Z\", status: \"pending\" }</span>\n <span style=\"color:#98c379;\">],</span>\n <span style=\"color:#98c379;\">lastTodoUpdate: \"2026-01-02T08:45:00Z\"</span>\n}\n</pre>\n</div>\n\n<div style=\"background:#1e1e1e;padding:12px;border-radius:4px;margin:12px 0;\">\n<p style=\"margin:0 0 8px 0;color:#61afef;font-weight:bold;\">Option B: Separate Progress Kontask</p>\n<pre style=\"font-family:monospace;font-size:0.85rem;margin:0;line-height:1.5;\">\n// Create a \"progress\" kontask type that's auto-updated\n// Client polls/subscribes for progress updates\n\n{\n type: \"progress\",\n title: \"Working: Fix authentication bug\",\n context: {\n parentRequestId: \"abc123\",\n todos: [...],\n workingHistory: [...],\n startedAt: \"...\",\n lastActivity: \"...\"\n }\n}\n</pre>\n</div>\n</div>\n\n<div style=\"background:#2d2d2d;padding:16px;border-radius:6px;margin-bottom:16px;\">\n<h3 style=\"color:#ff9800;margin:0 0 12px 0;\">Implementation Points</h3>\n\n<table style=\"width:100%;border-collapse:collapse;font-size:0.9rem;\">\n<tr style=\"border-bottom:1px solid #444;\">\n<th style=\"text-align:left;padding:8px;color:#e0e0e0;\">Component</th>\n<th style=\"text-align:left;padding:8px;color:#e0e0e0;\">Change</th>\n</tr>\n<tr style=\"border-bottom:1px solid #3d3d3d;\">\n<td style=\"padding:8px;\"><code>konsole/stream.ts</code></td>\n<td style=\"padding:8px;\">Detect TodoWrite calls, update kontask via MCP</td>\n</tr>\n<tr style=\"border-bottom:1px solid #3d3d3d;\">\n<td style=\"padding:8px;\"><code>konui/kontask-db.ts</code></td>\n<td style=\"padding:8px;\">Add <code>updateKontaskTodos()</code> method</td>\n</tr>\n<tr style=\"border-bottom:1px solid #3d3d3d;\">\n<td style=\"padding:8px;\"><code>dashboard-console.ts</code></td>\n<td style=\"padding:8px;\">Render todos from recovered kontask</td>\n</tr>\n<tr>\n<td style=\"padding:8px;\"><code>konui/router.ts</code></td>\n<td style=\"padding:8px;\">API endpoint to get progress by requestId</td>\n</tr>\n</table>\n</div>\n\n<div style=\"background:#2d2d2d;padding:16px;border-radius:6px;margin-bottom:16px;\">\n<h3 style=\"color:#9c27b0;margin:0 0 12px 0;\">Recovery Flow (After Change)</h3>\n<pre style=\"background:#1e1e1e;padding:12px;border-radius:4px;font-family:monospace;font-size:0.85rem;line-height:1.6;\">\n<span style=\"color:#7f848e;\">1. Client reconnects</span>\n<span style=\"color:#7f848e;\">2. Loads pendingRequestId from localStorage</span>\n<span style=\"color:#7f848e;\">3. Fetches kontask by requestId</span>\n<span style=\"color:#7f848e;\">4. If kontask has context.todos:</span>\n <span style=\"color:#98c379;\">→ Render todo list showing progress</span>\n <span style=\"color:#98c379;\">→ Show \"Claude was working on: {activeForm}\"</span>\n<span style=\"color:#7f848e;\">5. If kontask has output:</span>\n <span style=\"color:#98c379;\">→ Display completed output card</span>\n</pre>\n</div>\n\n<div style=\"background:#3d3d3d;padding:12px;border-radius:6px;border-left:4px solid #2196f3;\">\n<p style=\"margin:0;color:#e0e0e0;\"><strong>Key Insight:</strong> The kontask already has <code>requestId</code> for matching. Adding <code>context.todos</code> and updating it during streaming gives us persistent todo state without new storage.</p>\n</div>\n</div>",
"requestedAt": "2026-01-02T08:45:00Z",
"requestId": "b4240372-4ace-4b8e-a12e-5aaf4ab5b351",
"choices": [
{
"label": "Option A: Incremental updates",
"value": "Implement Option A - update the existing kontask context with todo state during streaming",
"primary": true
},
{
"label": "Option B: Progress kontasks",
"value": "Implement Option B - create a separate progress kontask type for in-flight work"
},
{
"label": "Explore alternatives",
"value": "Research other approaches to crash recovery for long-running Claude tasks"
}
]
},
"createdBy": "claude",
"createdAt": "2026-01-02T02:10:56.965Z",
"updatedAt": "2026-01-02T02:10:57.117Z",
"requestId": "b4240372-4ace-4b8e-a12e-5aaf4ab5b351",
"scope": "vibetools",
"tags": [
"kontasks",
"todos",
"recovery",
"konsole"
],
"sessionId": "dashboard",
"planSummary": "Analyzing todo persistence options for kontask crash recovery",
"targetUser": "claude"
}