| summary | WidgetKit snapshot pipeline + visibility troubleshooting for CodexBar widgets. | |||
|---|---|---|---|---|
| read_when |
|
WidgetSnapshotStorewrites compact JSON snapshots to the app-group container.- Widgets read the snapshot and render usage/credits/history states.
- The app writes snapshots after the main refresh pipeline and token-usage refreshes; narrow single-provider refresh paths may wait for the next snapshot write.
- If no snapshot is available, widgets fall back to preview/empty data.
Sources/CodexBarWidgetcontains timeline + views.- Keep data shape in sync with
WidgetSnapshotin the main app.
- CodexBar Switcher (
CodexBarSwitcherWidget): static provider switcher widget, small/medium/large. - CodexBar Usage (
CodexBarUsageWidget): configurable provider usage widget, small/medium/large. - CodexBar History (
CodexBarHistoryWidget): configurable usage-history chart, medium/large. - CodexBar Metric (
CodexBarCompactWidget): compact credits/today-cost/30-day-cost widget, small only.
The configurable provider widgets currently expose: Codex, Claude, Gemini, Alibaba, Antigravity, z.ai, Copilot, MiniMax, Kilo, OpenCode, and OpenCode Go.
Providers without a ProviderChoice case can still be present in the app snapshot, but they are not selectable from the widget configuration UI yet.
When widgets do not appear in the gallery at all, the issue is almost always registration, signing, or daemon caching (not SwiftUI code).
APP="/Applications/CodexBar.app"
WAPPEX="$APP/Contents/PlugIns/CodexBarWidget.appex"
WIDGET_ID="com.steipete.codexbar.widget" # debug builds use com.steipete.codexbar.debug.widget
ls -la "$WAPPEX" "$WAPPEX/Contents" "$WAPPEX/Contents/MacOS"
pluginkit -m -p com.apple.widgetkit-extension -v | grep -i codexbar || true
pluginkit -m -p com.apple.widgetkit-extension -i "$WIDGET_ID" -vv
Notes:
+= elected to use,-= ignored (PlugInKit elections).- If missing or ignored, force-add and re-elect:
pluginkit -a "$WAPPEX"
pluginkit -e use -p com.apple.widgetkit-extension -i "$WIDGET_ID"
- Check for duplicates (old installs or version precedence):
pluginkit -m -D -p com.apple.widgetkit-extension -i "$WIDGET_ID" -vv
If multiple paths appear, delete older installs and bump CFBundleVersion.
Widgets are loaded by system daemons. Any signing failure can hide the widget.
codesign --verify --deep --strict --verbose=4 /Applications/CodexBar.app
codesign --verify --strict --verbose=4 "$WAPPEX"
codesign --verify --strict --verbose=4 "$WAPPEX/Contents/MacOS/CodexBarWidget"
spctl --assess --type execute --verbose=4 /Applications/CodexBar.app
killall -9 pkd || true
sudo killall -9 chronod || true
killall Dock NotificationCenter || true
log stream --style compact --predicate '(process == "pkd" OR process == "chronod" OR subsystem CONTAINS "PlugInKit" OR subsystem CONTAINS "WidgetKit")'
- Widget bundle id should be
com.steipete.codexbar.widgetfor release andcom.steipete.codexbar.debug.widgetfor debug. NSExtensionPointIdentifiermust becom.apple.widgetkit-extension.- Bundle folder name should match:
CodexBarWidget.appex.
Optional: re-seed LaunchServices (rarely helps, but low risk):
/System/Library/Frameworks/CoreServices.framework/Frameworks/LaunchServices.framework/Support/lsregister -seed
If the widget appears but always shows preview data:
- App writes snapshot to fallback path while widget reads app-group container.
- Validate that both app and widget resolve the same app-group container.
See also: docs/ui.md, docs/packaging.md.