This implementation allows each platform to choose how to launch Steam (on Linux, we use the snap as the examples suggested before), and keeps Steam alive after an activity exits so that save sync, game updates, etc. can continue to run. Change written by Codex 5.2 on medium: Consider this GitHub issue https://github.com/aarmea/shepherd-launcher/issues/4. On Linux, an activity that uses the "steam" type should launch Steam via the snap as shown in the example configuration in this repository. Go ahead and implement the feature. I'm expecting one of the tricky bits to be killing the activity while keeping Steam alive, as we can no longer just kill the Steam snap cgroup. |
||
|---|---|---|
| .. | ||
| src | ||
| Cargo.toml | ||
| README.md | ||
shepherd-launcher-ui
Main launcher grid interface for Shepherd.
Overview
shepherd-launcher-ui is the primary user-facing shell for the Shepherd kiosk environment. It presents a grid of available entries (applications, games, media) and allows users to launch them.
This is what users see when no session is active—the "home screen" of the environment.
Features
- Entry grid - Large, touch-friendly tiles for each available entry
- Availability display - Visual indication of enabled/disabled entries
- Launch requests - Send launch commands to the service
- State synchronization - Always reflects service's authoritative state
Architecture
┌───────────────────────────────────────────────────────┐
│ Sway / Wayland Compositor │
│ │
│ ┌──────────────────────────────────────────────────┐ │
│ │ Launcher UI (fullscreen) │ │
│ │ │ │
│ │ ┌────────┐ ┌────────┐ ┌────────┐ ┌────────┐ │ │
│ │ │ │ │ │ │ │ │ │ │ │
│ │ │Minecraf│ │GCompris│ │ Movies │ │ Books │ │ │
│ │ │ │ │ │ │ │ │ │ │ │
│ │ └────────┘ └────────┘ └────────┘ └────────┘ │ │
│ │ │ │
│ │ ┌────────┐ ┌────────┐ │ │
│ │ │ │ │ │ │ │
│ │ │ ScummVM│ │Bedtime │ │ │
│ │ │ │ │ │ │ │
│ │ └────────┘ └────────┘ │ │
│ │ │ │
│ └──────────────────────────────────────────────────┘ │
└───────────────────────────────────────────────────────┘
Usage
Running
# With default socket path
shepherd-launcher
# With custom socket path
shepherd-launcher --socket /custom/path/shepherdd.sock
Command-Line Options
| Option | Default | Description |
|---|---|---|
-s, --socket |
$XDG_RUNTIME_DIR/shepherdd/shepherdd.sock |
Service socket path |
-l, --log-level |
info |
Log verbosity |
Grid Behavior
Entry Tiles
Each tile displays:
- Icon - Large, recognizable icon
- Label - Entry name
- Status - Enabled (bright) or disabled (dimmed)
- Time indicator - Max duration if started now (e.g., "30 min")
Enabled Entries
When an entry is enabled:
- Tile is fully visible and interactive
- Tapping sends
Launchcommand to service - Grid shows "Launching..." state
- On success: launcher hides, application starts
Disabled Entries
When an entry is disabled it is not displayed.
Launch Flow
User taps tile
│
▼
Launcher sends Launch command
│
▼
Grid input disabled
"Starting..." overlay shown
│
▼
┌─────┴─────┐
│ │
▼ ▼
Success Failure
│ │
▼ ▼
Launcher Error message
hides Grid restored
State Management
The launcher maintains a reactive state model:
struct LauncherState {
entries: Vec<EntryView>, // From service
current_session: Option<SessionInfo>,
connected: bool,
launching: Option<EntryId>,
}
Event Handling
| Event | Launcher Response |
|---|---|
StateChanged |
Update entry grid |
SessionStarted |
Hide launcher |
SessionEnded |
Show launcher |
PolicyReloaded |
Refresh entry list |
Visibility Rules
The launcher is visible when:
- No session is running, OR
- User explicitly returns to home (via HUD)
The launcher hides when:
- A session is actively running
- (Fullscreen app is in front)
Error Handling
Service Unavailable
If the service is not running at startup:
┌────────────────────────────────────────┐
│ │
│ System Not Ready │
│ │
│ Waiting for shepherd service... │
│ │
│ [Retry] │
│ │
└────────────────────────────────────────┘
Launch Failure
If launching fails:
- Error notification appears
- Grid is restored to interactive state
- User can try again or choose another entry
Connection Loss
If connection to service is lost:
- Entries become disabled
- Reconnection attempted automatically
- State refreshed on reconnection
Accessibility
- Touch-first - Large touch targets (minimum 44px)
- High contrast - Clear visual hierarchy
- Minimal text - Icon-first design
- Keyboard navigation - Arrow keys and Enter
- No hover-only interactions - All actions accessible via tap
Styling
The launcher uses a child-friendly design:
- Large, colorful icons
- Rounded corners
- Clear enabled/disabled distinction
- Smooth transitions
- Dark background (for contrast)
Dependencies
gtk4- GTK4 bindingstokio- Async runtimeshepherd-api- Protocol typesshepherd-ipc- Client implementationclap- Argument parsingtracing- Logging
Building
cargo build --release -p shepherd-launcher-ui
The resulting binary is named shepherd-launcher.
Relationship to Service
Critical: The launcher is purely a presentation layer. It:
- Displays what the service allows
- Sends launch requests
- Shows service state
It does not:
- Tracks time independently
- Decide availability
- Enforce policy
If the launcher crashes, the service continues enforcement. If the launcher is replaced, the system still works.