8.5 KiB
This prompt created the UI. It was run in the same conversation as the one that created shepherdd, and was also provided to Claude Opus 4.5 via VSCode Agent mode.
It was produced by ChatGPT after some back-and-forth in this conversation.
The output was committed as e2013eb694.
Now implement the UI that integrates with shepherdd as described below.
Linux / Wayland Launcher UI Specification
1. Purpose and scope
The Linux/Wayland launcher UI is the primary user-facing shell for a kiosk-style, child-friendly computing environment backed by shepherdd.
Its responsibilities are presentation and input only:
- display what
shepherddallows right now - request launches and stops
- display authoritative state (time remaining, warnings)
- never enforce policy on its own
The launcher must not:
- track time limits independently
- decide availability rules
- attempt to supervise or kill applications
If the launcher crashes or disconnects, shepherdd continues enforcement.
2. High-level architecture
The Linux UI is split into two cooperating Wayland clients:
- Launcher UI (main grid)
- HUD / Overlay UI (always visible)
Both are ordinary Wayland clients and communicate only with shepherdd over local IPC.
┌───────────────────────────────────────────┐
│ Sway (kiosk-configured compositor) │
│ │
│ ┌───────────────┐ ┌──────────────────┐ │
│ │ HUD Overlay │ │ Running App │ │
│ │ (layer-shell) │ │ (fullscreen) │ │
│ └───────────────┘ └──────────────────┘ │
│ │
│ ┌───────────────────────────────────────┐ │
│ │ Launcher UI (grid, home screen) │ │
│ └───────────────────────────────────────┘ │
└───────────────────────────────────────────┘
3. Compositor assumptions (Sway)
3.1 Required compositor features
The launcher assumes a Wayland compositor that supports:
-
wlr-layer-shell (for always-on HUD)
-
fullscreen surfaces
-
IPC or rules to:
- force fullscreen
- prevent workspace switching
- disable escape keybindings
Sway is the reference implementation.
3.2 Kiosk constraints to enforce in Sway config
The system must:
-
expose no user-visible workspaces
-
disable:
- Alt+Tab
- Mod+key bindings
- exit / reload bindings
-
force launched applications fullscreen
-
ensure layer-shell overlay is always topmost
The launcher UI must not rely on Sway configuration details, but it must assume these constraints hold.
4. Process model
4.1 Launcher UI process
-
GTK4 Wayland application
-
normal Wayland surface
-
visible only when:
- no session is running
- or user explicitly returns to “home”
4.2 HUD / Overlay process
- GTK4 Wayland application using layer-shell
- always visible, regardless of running app
- anchored to a screen edge (typically top)
4.3 Privilege
- runs as the same user as the compositor
- does not require elevated privileges
- all privileged actions go through
shepherdd
5. IPC contract with shepherdd
5.1 Connection
- Unix domain socket (path configurable)
- persistent connection
- reconnect logic required
5.2 Commands issued by the launcher UI
ListEntriesLaunch { entry_id }StopCurrentGetStateSubscribeEvents
5.3 Events consumed by launcher & HUD
StateChangedSessionStartedWarningIssuedSessionExpiredSessionEndedPolicyReloaded
The UI must treat daemon state as authoritative.
6. Launcher UI (main grid)
6.1 Visual layout
- Fullscreen window
- Grid of large, touch-friendly icons
- Each tile represents one
EntryViewfromshepherdd
Each tile must show:
- icon
- label
- enabled / disabled state
- disabled reason (optional text or icon)
6.2 Availability handling
For each entry:
-
If disabled:
- tile is visually muted
- tapping does nothing
- optional “why” tooltip (e.g. “Not available until 3pm”)
-
If enabled:
- tapping sends
Launch(entry_id) - UI transitions to “launching” state
- tapping sends
6.3 Launch feedback
When a launch is requested:
-
grid input is disabled
-
show:
- “Starting…” indicator
-
wait for:
SessionStarted→ transition away- or error → restore grid
6.4 Return to home
The launcher UI must be able to re-appear when:
- session ends
- user presses “close” in HUD (if allowed)
- daemon requests shell visibility
7. HUD / Overlay UI (always visible)
7.1 Placement and layer
- Wayland layer-shell
- layer:
overlay - exclusive zone: minimal (or none)
- must not be obscured by fullscreen apps
7.2 Required elements
The HUD must display, at minimum:
-
Time remaining
- authoritative countdown from daemon
- format:
MM:SSorH:MM:SS - visually emphasized when below warning thresholds
-
Battery level
- via UPower (local system API)
- percent + icon
- daemon does not own battery state
-
Volume
-
current output volume
-
mute state
-
controls may:
- send
SetVolumevia daemon - or adjust locally (implementation choice)
- send
-
-
Close / End session button
- sends
StopCurrent - availability depends on daemon state
- may be hidden or disabled for certain entries
- sends
-
Power button
-
opens a small modal:
- Suspend
- Shutdown
- Restart
-
actions are forwarded to daemon (daemon decides if allowed)
-
7.3 Warning presentation
On WarningIssued:
- show banner or modal in HUD
- severity reflected visually
- optional sound cue
- must not block rendering of underlying app
On SessionExpired:
- show “Time’s up” overlay
- remain visible until session ends and home returns
7.4 Failure handling
If daemon disconnects:
-
HUD must:
- show “Disconnected” indicator
- attempt reconnect
- not fabricate time remaining
8. Interaction between launcher and HUD
- Launcher and HUD do not communicate directly
- Both reflect the same daemon state
- HUD remains visible while launcher is hidden
- Launcher must ignore input while a session is running
9. Input and accessibility considerations
9.1 Input
- Touch-friendly sizing
- Mouse and keyboard supported
- No reliance on keyboard shortcuts for core actions
9.2 Accessibility
- High contrast mode recommended
- Large fonts
- Minimal text; icon-first design
- Avoid hover-only affordances
10. Error states and recovery
10.1 Daemon unavailable at startup
-
Show blocking error screen:
- “System not ready”
- retry button
-
Do not allow launching without daemon
10.2 App fails to launch
- Daemon emits failure
- Launcher returns to grid
- Optional error message
10.3 Session ends unexpectedly
- HUD updates immediately
- Launcher reappears automatically
11. Non-functional requirements
11.1 Robustness
- UI must tolerate daemon restarts
- UI must tolerate compositor restarts (best effort)
11.2 Determinism
- Countdown is driven only by daemon events/state
- UI must never infer remaining time independently
11.3 Maintainability
- No daemon logic embedded in UI
- All policy logic treated as opaque
12. Implementation constraints and recommendations
- Toolkit: GTK4
- Language: Rust (gtk-rs) preferred
- Layer-shell:
gtk4-layer-shell(or equivalent) - IPC client: reuse
shepherd-apiandshepherd-ipctypes
13. Explicit non-goals
- Embedding third-party apps inside the launcher
- Replacing the compositor
- Managing system accounts or users
- Performing enforcement locally in UI
14. Success criteria
The launcher UI is considered correct if:
- It can fully drive the system using only daemon IPC.
- It remains usable while arbitrary fullscreen apps (VMs, emulators) run underneath.
- Time warnings and expiry are always visible and accurate.
- Replacing the launcher UI with another client would not weaken enforcement.