name: viewing-tasks
description: >
Renders task data as interactive HTML dashboards (Kanban, List, Calendar, Gantt).
In cli / claude-desktop the dashboard is served by a local view server on
localhost:3456. In Cowork the dashboard is registered as a Live Artifact that
fetches Notion data directly via window.cowork.callMcpTool.
Use this skill whenever the user wants to see tasks visually — board views,
timelines, calendars, or any kind of task visualization or dashboard display.
Read-only views only. For any write, or a scoped filter that may lead to a
mutation, route through managing-tasks instead.
Triggers on: "kanban", "list view", "show tasks", "view", "visualize",
"gantt", "calendar", "board", "timeline", "display tasks", "open dashboard".
user-invocable: true
Waggle — Tasks Dashboard
You render the user's tasks as an interactive dashboard. The transport depends on the execution environment; the user-visible interface (Kanban / List / Calendar / Gantt) is the same in every environment.
Output Discipline
This skill runs as a multi-step pipeline, but the user only needs its outcomes. Do not narrate step transitions ("Now I'll...", "X done, next Y") and do not relay protocol internals — provider detection, config/schema checks, cache state, validation plumbing, view-server data pushes (POST /api/data). Surfacing them buries what actually matters.
Emit user-facing text only when it changes something for the user:
- a prompt or confirmation that needs their input
- an error or a warning
- an intermediate result that changes the outcome
- the final result summary
The view server URL (http://localhost:3456) and dashboard status are this skill's final
result and must always surface.
Session Bootstrap
Invoke the bootstrap-session skill to establish the active provider, the current user, and execution_environment. Skip if these are already set in this conversation.
Mode Selection
Pick the transport based on execution_environment (set by bootstrap):
cowork→ use Cowork Live Artifact Mode (below). localhost is not reachable from the user's browser in Cowork.cli/claude-desktop→ use Localhost Server Mode (below). The local view server hosts the dashboard athttp://localhost:3456.
The two modes use the same Task data shape and the same set of view renderers (kanban / list / calendar / gantt). Only the transport and the host shell differ.
Cowork Live Artifact Mode
In Cowork, the dashboard is a single Live Artifact (id = "waggle-tasks") that bundles all four view renderers with a tab strip at the top. The artifact fetches Notion data itself via the notion-query tool from the notion-extension MCP; refresh is driven by Cowork's built-in ↻ button or the in-page refresh, both of which re-run the artifact JS.
Steps
Resolve
tasksDatabaseIdfromheadless_config(set during bootstrap). Ifcurrent_teamis set, capturecurrent_team.id/current_team.namefor baking into the artifact.Determine the assignee to scope the artifact to. By default this is
current_user.id(the person opening the artifact almost always wants their own open tasks, not the entire workspace). If the user has explicitly asked to view another person's tasks ("show Alice's board", "build a dashboard for the platform team lead"), resolve that person via thelooking-up-membersskill and use their Notion user ID instead.Resolve the Notion-query MCP tool name. Look through your available MCP tools and find the one whose unqualified name is
notion-queryand that comes from the notion-extension MCP (its full name typically looks likemcp__notion-extension__notion-query, but the exact prefix depends on the installed extension version's manifest — never hardcode it). Use that exact, full tool name as the 5th argument to the generator below and as the value in themcp_toolsarray when callingcreate_artifact/update_artifact. If you cannot find such a tool, surface the failure to the user and stop — the artifact cannot operate without it.Generate the bundled HTML. The 4th argument is the assignee Notion user ID; the 5th argument is the resolved MCP tool name from Step 3. The bundle will server-side filter to that assignee AND exclude Done/Cancelled at the Notion query layer:
bash "${CLAUDE_SKILL_DIR}/scripts/generate-cowork-artifact.sh" \ "<tasksDatabaseId>" \ "<current_team.id or empty>" \ "<current_team.name or empty>" \ "<assignee notion user id, e.g. current_user.id>" \ "<the full MCP tool name you resolved in Step 3>" \ > /tmp/waggle-tasks.htmlPass an empty string for the 4th argument only if the user has explicitly asked for an unscoped view across all assignees; the bundle then shows all open tasks with an informational banner. Status exclusion (Done + Cancelled) is always applied — these terminal states are never useful in the active dashboard.
Call
mcp__cowork__list_artifacts()and check whether the response includes an entry withid == "waggle-tasks".If the artifact already exists, refresh it in place via
update_artifact(don't create a duplicate):mcp__cowork__update_artifact({ id: "waggle-tasks", html_path: "/tmp/waggle-tasks.html", update_summary: "[REFRESH] regenerated against latest schema / team / assignee scope", mcp_tools: ["<the full MCP tool name you resolved in Step 3>"] })This re-bakes the latest
databaseId/currentTeam/assigneeUserIdand picks up any code changes since the last registration. The user gets the Cowork approval prompt on update.If the artifact does not exist, register it via
create_artifact:mcp__cowork__create_artifact({ id: "waggle-tasks", html_path: "/tmp/waggle-tasks.html", description: "Waggle Tasks Dashboard — Kanban / List / Calendar / Gantt", mcp_tools: ["<the full MCP tool name you resolved in Step 3>"] })Clean up the temp file:
rm -f /tmp/waggle-tasks.html. Tell the user to open the waggle-tasks Live Artifact panel in the Cowork sidebar (or, on update, reload the existing panel).
Cowork-mode behavior
- The artifact bundles Kanban / List / Calendar / Gantt; the active tab is persisted per-user in
localStorage(waggle-tasks-active-tab-v1). - Each artifact reload re-fetches via the resolved notion-query MCP tool (paginated, cap 1000 rows). The fetch is server-side filtered to the baked
assigneeUserIdand always excludesStatus == Done/Status == Cancelled; the bundledfilter-bar.jsnarrows further on the client. The status badge reads "Live (Cowork)" when the fetch succeeds. To switch the bound assignee, re-run/viewing-taskswith the new person's name — the skill regenerates and callsupdate_artifactwith the new scope. - The artifact is read-only. Mutating Notion tools are deliberately not declared in
mcp_toolsyet; inline-edit UI will come in a later skill release and will widenmcp_toolsviaupdate_artifact. - Cold-start race (GitHub Issue #55788): on either Windows or macOS the artifact's first call to
callMcpToolmay fail with HTTP 400 in a cold-start state. Workaround: ask the user to invoke any Notion MCP tool from the Cowork chat once before opening the artifact, then reload the panel. - Custom user-defined views are managed by the
managing-viewsskill and registered as separatewaggle-view-<slug>artifacts.
Troubleshooting
- "Cowork runtime unavailable" banner in the artifact: the cold-start race fired. Reload the panel, or have the user run any Notion MCP tool from chat first.
- "Failed to load tasks: ...": open DevTools on the artifact panel (right-click → Inspect). Network tab shows the
callMcpToolrequest; Console shows any JS errors. Verify the bakeddatabaseIdmatches the activetasksDatabaseId. Tool call failed: 400from the artifact (with chat-mode calls succeeding): known Cowork-platform issue with extension tool prefixes that contain underscores. Isolation testing confirms the bridge accepts prefixes with uppercase letters (e.g.mcp__EchoUpper__...works) but rejects prefixes with underscores (e.g.mcp__echo_lower_only__...returns 400). The prefix is derived from the extension manifest'sdisplay_name; a manifest with adisplay_namecontaining whitespace gets normalized with whitespace converted to_, producing a prefix that the Live Artifact bridge currently rejects, even though chat-mode calls work. Mitigation: install notion-extension v0.5.0+ which dropsdisplay_nameand yields a hyphenatedmcp__notion-extension__...prefix that the bridge accepts. Older v0.4.x installs keep working from chat but not from Live Artifact.- Dashboard shows stale data: click the Cowork built-in ↻, which re-executes the artifact JS and re-fetches.
- Stale artifact (schema changed, wrong team, wrong assignee): re-run
/viewing-tasks— the skill regenerates and callsupdate_artifactwith the latestdatabaseId/ team / assignee binding. - "My dashboard is empty / shows the wrong person's tasks": the baked
assigneeUserIdmay not match the user's expectations. Re-run/viewing-tasks(defaults tocurrent_user.id) or/viewing-tasks <name>to scope to someone else. To see everyone, ask for an unscoped regeneration explicitly.
Localhost Server Mode
In cli / claude-desktop, the dashboard is served from a local Hono server on http://localhost:3456. The skill ensures the server is running, pushes the current task snapshot, and opens the browser.
Starting the Server
cd "${CLAUDE_SKILL_DIR}/server" && npm ci --silent && npx tsx src/index.ts &
Before starting, check if it's already running:
curl -s http://localhost:3456/api/health 2>/dev/null
If the health check succeeds, the server is already running. Do NOT start a second instance.
Available Views
| View | URL | Status |
|---|---|---|
| View Selector | http://localhost:3456/ | Available |
| List | http://localhost:3456/list.html | Available |
| Kanban | http://localhost:3456/kanban.html | Available |
| Calendar | http://localhost:3456/calendar.html | Available |
| Gantt | http://localhost:3456/gantt.html | Available |
Opening a View
After ensuring the server is running, open the appropriate URL in the user's browser:
# macOS
open http://localhost:3456/kanban.html
# Linux
xdg-open http://localhost:3456/kanban.html
# WSL
wslview http://localhost:3456/kanban.html
Detect the platform and use the appropriate command.
Initializing Data After Start
After starting the server, push current task data so the view is populated. Follow the Pushing Data to View Server section in the active provider's SKILL.md to:
- Fetch all tasks from the data source
- Format as
{ "tasks": [...], "updatedAt": "<ISO timestamp>", "currentTeam": { "id": "<id>", "name": "<name>" } }(includecurrentTeamifcurrent_teamis set from resolving-identity; omit if null) - POST to
http://localhost:3456/api/data
Custom Views
Users can create custom visualizations using the managing-views skill. Custom views are served at /custom/<slug>.html.
Opening a Custom View
# macOS
open http://localhost:3456/custom/<slug>.html
# Linux
xdg-open http://localhost:3456/custom/<slug>.html
# WSL
wslview http://localhost:3456/custom/<slug>.html
Listing Custom Views
ls ~/.waggle/views/*.html
To create, delete, or regenerate custom views, use the managing-views skill.
View Features (Localhost Mode)
All views support:
- Real-time updates: Connected to SSE at
/api/events. Changes made via managing-tasks skill are reflected automatically. - Client-side filtering: Filter by Status, Priority, search text
- Click-to-copy: Click a task to copy its ID for use in Claude Code
- Dark mode: Default dark theme
Troubleshooting (Localhost Mode)
If views don't update after task changes:
- Check the server is running:
curl http://localhost:3456/api/health - Manually push data: use the managing-tasks skill to query tasks and POST to
/api/data - Check server logs in the terminal where it's running