Skip to content

Add Dynamic Island Live Activity for chat streaming#8

Open
zmanian wants to merge 2 commits intomcintyre94:mainfrom
zmanian:live-activity
Open

Add Dynamic Island Live Activity for chat streaming#8
zmanian wants to merge 2 commits intomcintyre94:mainfrom
zmanian:live-activity

Conversation

@zmanian
Copy link
Contributor

@zmanian zmanian commented Feb 24, 2026

Summary

ActivityKit Live Activity shows Claude's progress in the Dynamic Island and on the Lock Screen while the app is backgrounded. Inspired by Chowder-iOS.

  • Dynamic Island compact: Colored status dot (blue = active, green = done) and current intent text
  • Dynamic Island expanded: Sprite name, current tool, step count, and previously completed tool
  • Lock Screen banner: Intent card stack with depth effect and live timer
  • Payload safety: Truncate userTask (200 chars) and intent strings (100 chars) to stay under ActivityKit's 4KB limit
  • Diagnostics: Surface startActivity failures via return value and lastError property, log with activity IDs

Note: This PR is stacked on #7 (thinking shimmer) because it uses activityLabel from ToolUseCard. Merge #7 first.

New files

  • Wisp/Models/WispActivityAttributes.swift -- shared ActivityKit attributes model
  • Wisp/Services/LiveActivityManager.swift -- singleton managing Activity lifecycle with debounced updates
  • WispActivityWidget/WispLiveActivity.swift -- Dynamic Island compact/expanded + Lock Screen banner views
  • WispActivityWidget/WispActivityWidgetBundle.swift -- widget bundle entry point
  • WispActivityWidget/Info.plist -- NSExtension configuration for WidgetKit
  • Wisp/Wisp.entitlements, WispActivityWidget/WispActivityWidget.entitlements -- entitlements

Modified files

  • Wisp/ViewModels/ChatViewModel.swift -- hooks for Live Activity start/update/end tied to NDJSON event flow
  • Wisp.xcodeproj/project.pbxproj -- WispActivityWidget extension target, embed phase, NSSupportsLiveActivities

Test plan

  • Build succeeds for both Wisp and WispActivityWidget targets
  • All existing tests pass
  • Send a tool-using prompt -- verify Dynamic Island shows status dot + current intent
  • Verify Lock Screen banner shows sprite name, intent cards with depth effect, live timer
  • Verify activity ends with green checkmark when Claude responds with text
  • Verify activity dismisses after ~8 seconds on completion
  • Test with long prompts (>200 chars) -- should truncate without crashing

Generated with Claude Code

@mcintyre94
Copy link
Owner

Thanks, this is really cool! I'm going to hold off on merging it for now because I want to think a bit more about how I'd like this to work with multiple chats which is how I'm often using Wisp.

@zmanian
Copy link
Contributor Author

zmanian commented Feb 26, 2026

The current thing has its flaws. Happy to brainstorm improving it.

@mcintyre94
Copy link
Owner

mcintyre94 commented Mar 1, 2026

Some not-super-well-organised thoughts:

  • Apparently iOS does handle multiple activities for a single app well, so that's not a blocker
  • I really like dynamic island as a UI and want it for Wisp!
  • I think it makes sense to ship this after we have notifications for the 'Done' status, so we can complete tasks in the dynamic island when the app is backgrounded. Would link well with notifications for that
  • When the app is foregrounded we can do much richer updates based on streaming tool use. But our notification system won't handle that granularity (ie no tool use hook) because it gets into data I don't want people sending to my server
  • We now have automatic chat naming, which should make this more useful

zmanian and others added 2 commits March 15, 2026 12:54
ActivityKit Live Activity shows Claude's progress in the Dynamic Island
and Lock Screen while the app is backgrounded. Compact view shows a
status dot and current intent; expanded view adds sprite name, step
count, and previous completed intent. Lock Screen banner shows intent
card stack with depth effect and a live timer.

New files: WispActivityAttributes (shared model), LiveActivityManager
(debounced singleton), WispActivityWidget extension (WispLiveActivity +
bundle). ChatViewModel hooks start/update/end the activity at tool use,
tool result, first text response, and result events.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Truncate userTask (200 chars) and intent strings (100 chars) to stay
under ActivityKit's 4KB payload limit. Surface startActivity failures
via return value and lastError property. Improve logging with activity
IDs.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants