Buddy Animation System
Relevant source files
The following files were used as context for generating this wiki page:
The Buddy Animation System is a core visual component of the Buddi application, responsible for rendering and animating unique ASCII-based companion characters. These characters serve as reactive indicators for the state of Claude Code Integration, changing their behavior and appearance based on whether the AI is idle, working, reading, sleeping, or encountered an error.
The system utilizes a combination of deterministic generation (based on system identity) and real-time state management to provide a personalized experience for each user. It supports 18 distinct species, multiple eye types, rarity levels, and customizable hats, all rendered through a monospaced ASCII art pipeline.
Sources: README.md:27-30, buddi/Buddi/Buddy/BuddyManager.swift:10-15
System Architecture
The animation system follows a clear separation of concerns between state detection, data generation, logic calculation, and UI rendering.
This diagram illustrates the flow of data from the initial generation of a buddy's identity to the final rendering of animation frames in the SwiftUI views.
Sources: buddi/Buddi/Buddy/BuddyManager.swift:18-28, buddi/Buddi/Buddy/SpriteAnimator.swift:10-16
Core Components
| Component | Responsibility |
|---|---|
| BuddyDetector | Handles the deterministic "roll" of species, eyes, rarity, and hats based on the system user ID or Claude configuration. |
| BuddyManager | A singleton that holds the BuddyIdentity and SpriteAnimator. It applies user overrides from settings to the base identity. |
| SpriteAnimator | A logic class that owns the animation timer and publishes the current rendered ASCII string based on the active BuddyTask. |
| SpriteFrameLogic | A stateless utility that computes specific frame transitions (blinks, shifts, scrolls) for various tasks. |
| ASCIISpriteView | SwiftUI view responsible for rendering the single-line buddy face, typically used in the notch or compact HUDs. |
| ASCIIFullSpriteView | Multi-line view that renders complete buddy sprites with smooth frame cycling using TimelineView. |
Sources: buddi/Buddi/Buddy/BuddyDetector.swift:7-25, buddi/Buddi/Buddy/BuddyManager.swift:10-25, buddi/Buddi/Buddy/SpriteAnimator.swift:10-25, buddi/Buddi/Buddy/ASCIISpriteView.swift:5-15
Identity and Customization
Buddies are generated using a deterministic hashing algorithm (Wyhash) and a seed generator (Mulberry32). This ensures that unless overridden, a user's buddy remains consistent across app launches while being unique to their system identity.
Sources: buddi/Buddi/Buddy/BuddyDetector.swift:11-20
Identity Attributes
- Species: 18 varieties including duck, cat, dragon, robot, and mushroom.
- Rarity: Levels that determine the color of the buddy (Common, Rare, etc.).
- Eyes: Different expressions such as dots, crosses, or shifts.
- Hats: Cosmetic additions typically tied to rarity levels.
The BuddyManager allows users to apply overrides to these attributes via the app settings. When an override is changed, the BuddyManager refreshes the effectiveIdentity, which automatically triggers the SpriteAnimator to update its rendering.
Sources: buddi/Buddi/Buddy/BuddyManager.swift:30-45, buddi/Buddi/Settings/ClaudeCodeSettings.swift:100-115
Animation States (BuddyTask)
The SpriteAnimator updates its behavior based on the BuddyTask assigned to it. Each task has a specific animation interval and unique logic for frame modification.
This sequence shows how external events (like Claude Code processing) translate into visual state changes.
Sources: buddi/Buddi/Buddy/SpriteAnimator.swift:18-35, buddi/Buddi/Buddy/SpriteAnimator.swift:50-65
Animation Logic Table
| Task | Interval | Visual Logic |
|---|---|---|
idle | 0.5s | Deterministic sequence of frames with occasional eye blinks (-). |
working | 0.4s | Toggles a cursor character (|) next to the base face. |
reading | 0.8s | Shifts eye positions to simulate scanning text. |
sleeping | 1.2s | Replaces eyes with dashes and scrolls "zzz" suffixes. |
error | 0.5s | Replaces eyes with "X" and tints the foreground color to red. |
Sources: buddi/Buddi/Buddy/SpriteAnimator.swift:70-85, buddi/Buddi/Buddy/SpriteAnimator.swift:90-110, buddi/Buddi/Buddy/ASCIISpriteView.swift:20-25
Rendering Implementation
Rendering is split between simple faces and full-body sprites.
Compact Rendering
The ASCIISpriteView uses a monospaced Menlo 16px font to ensure ASCII alignment. It observes a SpriteAnimator instance and displays the frameString property.
Sources: buddi/Buddi/Buddy/ASCIISpriteView.swift:5-15
struct ASCIISpriteView: View {
@ObservedObject var animator: SpriteAnimator
let rarity: BuddyRarity
let isError: Bool
var body: some View {
Text(animator.frameString)
.font(.system(size: 16, design: .monospaced))
.foregroundColor(textColor)
.lineLimit(1)
.fixedSize()
.drawingGroup()
}
}
Sources: buddi/Buddi/Buddy/ASCIISpriteView.swift:9-15
Full Sprite Rendering
The ASCIIFullSpriteView provides a multi-line rendering for the expanded notch panel. It uses a TimelineView to drive animations independently of the global SpriteAnimator timer when high-fidelity multi-line rendering is required. It calls SpriteData.renderFrame to construct the full ASCII body lines based on species, eyes, and current tick.
Sources: buddi/Buddi/Buddy/ASCIISpriteView.swift:30-45
Conclusion
The Buddy Animation System creates a responsive, character-driven interface for monitoring background AI tasks. By combining a deterministic identity generation system with a robust state-based animation engine, it provides users with a glanceable and personalized way to track the status of their Claude Code sessions. The system's reliance on ASCII art ensures high performance and low resource overhead while maintaining a distinct visual style.