feat(profile): refuse writes while Elgato app is running + restart_app path fix#16
Conversation
The Elgato Stream Deck app keeps every profile in memory and rewrites the on-disk manifests from its snapshot when it quits. Any edit made while the app is running is silently discarded the next time the app closes, which is exactly what bit a live-hardware smoke test of the previous PR. - Raise a new StreamDeckAppRunningError from write_page when the app is running, with a remediation message pointing callers at the auto_quit_app opt-in and the follow-up restart_app call. - Add auto_quit_app=False param on write_page. When True and the app is running, quit it cleanly (AppleScript quit first, killall fallback) before writing; the report is surfaced in the write_page response. - Rework restart_app to launch by explicit bundle path. The old `open -a "Stream Deck"` / `open -a "Elgato Stream Deck"` name lookup returns LSOpen error -600 on some macOS installs; launching by path bypasses LaunchServices. STREAMDECK_APP_PATH env var overrides the default `/Applications/Elgato Stream Deck.app`. - Expose reusable is_stream_deck_app_running() and stop_stream_deck_app() helpers so other future entrypoints can share the same lifecycle logic. - Update the README workflow section to spell out the quit → write → relaunch cycle and the env-var escape hatch. - New tests (5) cover the refuse/auto-quit branches, the restart-by-path path, and the missing-bundle error. An autouse fixture stubs the process check so existing tests are unaffected regardless of whether the contributor has the app running locally. Scope: unchanged tool count (6). auto_quit_app is a single additive field on the existing write_page tool. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Adds safeguards to prevent Stream Deck profile writes from being silently lost while the Elgato desktop app is running, and fixes streamdeck_restart_app to relaunch via an explicit .app path (with an env-var override) to avoid macOS LaunchServices -600 failures.
Changes:
- Refuse
write_pagewhen the Stream Deck app is running unless callers opt in viaauto_quit_app=True(and surface a dedicated error type). - Add
auto_quit_appto the MCP tool schema and server call path. - Rework
restart_apptoopenan explicit app bundle path withSTREAMDECK_APP_PATHoverride; document the new workflow in the README; add tests.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 4 comments.
| File | Description |
|---|---|
profile_manager.py |
Adds app-running detection/stop helpers, blocks writes while app is running, and changes app restart logic to launch by path. |
profile_server.py |
Extends streamdeck_write_page schema with auto_quit_app and returns a dedicated warning message for the new running-app error. |
tests/test_profile_manager.py |
Adds tests for the running-app refusal, auto-quit path, and explicit restart-app path behavior. |
README.md |
Documents the required quit → write → restart workflow and the STREAMDECK_APP_PATH override. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
@copilot apply changes based on the comments in this thread |
…fore write, validate path before stop Agent-Logs-Url: https://github.com/verygoodplugins/streamdeck-mcp/sessions/bf3b8260-ea35-455c-99cf-579444999ff4 Co-authored-by: jack-arturo <13076544+jack-arturo@users.noreply.github.com>
Agent-Logs-Url: https://github.com/verygoodplugins/streamdeck-mcp/sessions/bf3b8260-ea35-455c-99cf-579444999ff4 Co-authored-by: jack-arturo <13076544+jack-arturo@users.noreply.github.com>
Applied all four review changes in commit
Warning Firewall rules blocked me from connecting to one or more addresses (expand for details)I tried to connect to the following addresses, but was blocked by firewall rules:
If you need me to access, download, or install something from one of these locations, you can either:
|
|
@copilot resolve the merge conflicts in this pull request |
Co-authored-by: jack-arturo <13076544+jack-arturo@users.noreply.github.com>
Resolved in commit |
🤖 I have created a release *beep* *boop* --- ## [0.3.0](v0.2.0...v0.3.0) (2026-04-28) ### Features * **icons:** bundle Material Design Icons for offline glyph rendering ([#19](#19)) ([459d410](459d410)) * **profile:** preserve encoder controller + Stream Deck + XL layout ([#15](#15)) ([f4a8402](f4a8402)) * **profile:** refuse writes while Elgato app is running + restart_app path fix ([#16](#16)) ([e1cb4e3](e1cb4e3)) * **skill:** streamdeck-designer Agent Skill + MCP transport hardening ([#22](#22)) ([fd3ec6f](fd3ec6f)) * **touchstrip:** expose $X1/$A0/$A1/$B1/$B2/$C1 encoder layouts ([#21](#21)) ([efa66e4](efa66e4)) * **touchstrip:** per-segment icon and background on Stream Deck + / + XL ([#20](#20)) ([a41a31c](a41a31c)) ### Bug Fixes * add Stream Deck XL and missing device layouts ([#10](#10)) ([c89435b](c89435b)) * **profile:** correct Stream Deck + XL keypad layout to 9x4 ([#18](#18)) ([d6da4b2](d6da4b2)) * **profile:** map 20GBD9901 to Stream Deck + (4 dials + 4x2 keypad) ([#25](#25)) ([da0ada5](da0ada5)) --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Summary
Follow-up to #15. Closes a silent data-loss hole and fixes a pre-existing bug in the app-restart helper — both surfaced by the Phase 1 on-device smoke test.
streamdeck_write_pagewhile the app is running are silently wiped the next time it closes (observed live during Phase 1 testing). This PR makes `write_page` refuse to run while the app is up and exposes a single additive `auto_quit_app` opt-in field for callers that want the tool to quit it for them (AppleScript → killall fallback).Workflow (added to README)
Test plan
Dependencies
Orthogonal to #15 — no merge-order requirement. Either can land first.
🤖 Generated with Claude Code