# \[APP\]\[Pro\] Python Script

**URL:** <https://community.homey.app/t/app-pro-python-script/157001>\
**Category:** Apps\
**Tags:** app, homey-pro\
**Created:** [July 7, 2026, 6:22pm UTC](https://community.homey.app/t/app-pro-python-script/157001 "2026-07-07T18:22:12Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![JaccoH](https://sea1.discourse-cdn.com/flex025/user_avatar/community.homey.app/jaccoh/32/33966_2.png) [@JaccoH](https://community.homey.app/u/JaccoH)\
**Post date:** [July 7, 2026, 6:22pm UTC](https://community.homey.app/t/app-pro-python-script/157001/1 "2026-07-07T18:22:12Z")

</div>

Hi all,

I built a Homey app that lets you run Python code directly from Advanced Flows.

Three flow cards:

Run Script — Python inline in the card, sandboxed (no network, no filesystem). Good for  
logic and calculations. Output: return\_value and error flow tokens.

Run Script with Packages — full Python with pip packages. Install requests, numpy,  
anything. Packages are cached in a virtual environment. Full Homey API access.

Run Named Script — save scripts in the built-in IDE, call them by name from any flow.  
Sandbox mode and venv configured in the IDE, not the card.

* * *

From non-sandboxed scripts (Run Script with Packages, Run Named Script):

```
# Read a logic variable
value = await homey.logic.get_variable("temperature")

# Read or control a device capability
state = await homey.devices.get_capability(device_id, "onoff")
await homey.devices.set_capability(device_id, "dim", 0.5)

# Trigger a flow (add the "Flow triggered from Python" trigger card to that flow first)
await homey.flow.trigger("my-tag")

return "done"

```

Note: homey.logic.set\_variable() is not supported — Homey restricts logic variable  
writes to the HomeyScript app only.

Note: homey.logic, homey.devices, and homey.flow are NOT available in the sandboxed  
“Run Script” card — they raise RuntimeError. Use return to pass values to the flow.

* * *

Example — fetch live weather (Run Script with Packages, venv with requests installed):

```
import requests
r = requests.get("https://api.open-meteo.com/v1/forecast?latitude=52.37&longitude=4.90&current=temperature_2m")
return r.json()["current"]["temperature_2m"]

```

The return value becomes the return\_value flow token. If the script raises an exception,  
the error flow token is set automatically.

* * *

IDE — settings page with Monaco editor (same as VS Code), Python syntax highlighting,  
run directly from the IDE, manage virtual environments.

Install: Python Script | Homey  
Source: [GitHub - jaccoh/homey-pythonscript: A Homey app to execute Python script in cards · GitHub](https://github.com/jaccoh/homey-pythonscript)

Requires Homey Pro (local) or SHS v13.0.0+. Bugs and PRs welcome.

* * *

Changelog

v0.4.0

- Fixed: scripts that take longer than ~10s (e.g. controlling a slow-moving  
device) always returned an empty return\_value in the IDE, even though the  
script itself succeeded. Homey’s Settings-page client enforces a hard,  
non-configurable ~10s request timeout — the IDE now kicks off the script  
as a background job and polls for the result instead of waiting on one  
request.
- Fixed: missing timeout arg on the Run Named Script card
- Added: timeout field to the IDE’s script tester

v0.3.2

- Fixed: new script name now appears in dropdown immediately after creating,  
without needing to save first

v0.3.1

- App Store compliance: plain text readme, new icon, real screenshot

v0.3.0

- error flow token now declared on all cards — use it in subsequent flow cards
- Sandboxed card: homey.logic/devices/flow now raise a clear error instead of  
silently doing nothing (they were never supported in sandbox mode)
- Fixed: script syntax errors in non-sandboxed cards now surface as an error  
instead of silently succeeding with an empty return value
- Fixed: concurrent bridge calls no longer race on the IPC channel
- Removed dead code (sandbox.py, unused HomeyContext internals)

v0.2.3

- homey.flow.trigger(“tag”) working via trigger card mechanism
- homey.logic.get\_variable() — read logic variables from Python
- homey.devices.get\_capability() / set\_capability() — read and control devices
- Fixed: sandboxed card could not be killed on timeout (now uses subprocess)
- Fixed: IPC pump robustness (KeyError, BrokenPipe, subprocess leak)

v0.2.2

- Initial release

---

<div class="post-metadata">

**Author:** ![Jero](https://sea1.discourse-cdn.com/flex025/user_avatar/community.homey.app/jero/32/17556_2.png) [@Jero](https://community.homey.app/u/Jero)\
**Post date:** [July 9, 2026, 9:40am UTC](https://community.homey.app/t/app-pro-python-script/157001/3 "2026-07-09T09:40:47Z")

</div>

Did you even run your own app? Seems your Claude has completely hallucinated stuff.

 ![image](https://us1.discourse-cdn.com/flex025/uploads/athom/original/3X/b/9/b937b0bb0ac66617f7d1cbd0a456b1cbc235651d.png)

---

<div class="post-metadata">

**Author:** ![JaccoH](https://sea1.discourse-cdn.com/flex025/user_avatar/community.homey.app/jaccoh/32/33966_2.png) [@JaccoH](https://community.homey.app/u/JaccoH)\
**Post date:** [July 9, 2026, 4:42pm UTC](https://community.homey.app/t/app-pro-python-script/157001/4 "2026-07-09T16:42:00Z")

</div>

Ofcourse I did, I’m running it as I speak to open and close curtains via Python. I’ll have a look if I can reproduce this.

---

<div class="post-metadata">

**Author:** ![JaccoH](https://sea1.discourse-cdn.com/flex025/user_avatar/community.homey.app/jaccoh/32/33966_2.png) [@JaccoH](https://community.homey.app/u/JaccoH)\
**Post date:** [July 9, 2026, 4:45pm UTC](https://community.homey.app/t/app-pro-python-script/157001/5 "2026-07-09T16:45:10Z")

</div>

by the way, I clearly stated its a very very early version… so… cut me some slack.. it really works

---

<div class="post-metadata">

**Author:** ![JaccoH](https://sea1.discourse-cdn.com/flex025/user_avatar/community.homey.app/jaccoh/32/33966_2.png) [@JaccoH](https://community.homey.app/u/JaccoH)\
**Post date:** [July 9, 2026, 6:23pm UTC](https://community.homey.app/t/app-pro-python-script/157001/6 "2026-07-09T18:23:35Z")

</div>

Please try 0.3.0 like so:

 ![image](https://us1.discourse-cdn.com/flex025/uploads/athom/original/3X/9/a/9a7b3b7fead9ec9233b1142abdc152d4e309acf5.png)  
 ![image](https://us1.discourse-cdn.com/flex025/uploads/athom/original/3X/6/2/624b3200e1ed76b2870cabc8309adc40ff80d0a4.png)

---

<div class="post-metadata">

**Author:** ![JaccoH](https://sea1.discourse-cdn.com/flex025/user_avatar/community.homey.app/jaccoh/32/33966_2.png) [@JaccoH](https://community.homey.app/u/JaccoH)\
**Post date:** [July 28, 2026, 1:45pm UTC](https://community.homey.app/t/app-pro-python-script/157001/7 "2026-07-28T13:45:54Z")

</div>

I’ve released 0.4.0 to test.

> **[Python Script | Homey](https://homey.app/en-nl/app/nl.hoeve.pythonscript/Python-Script/test/)**
>
> Run Python code from Advanced Flows

Review is pending for release.

---

<div class="post-metadata">

**Author:** ![JaccoH](https://sea1.discourse-cdn.com/flex025/user_avatar/community.homey.app/jaccoh/32/33966_2.png) [@JaccoH](https://community.homey.app/u/JaccoH)\
**Post date:** [July 29, 2026, 1:21pm UTC](https://community.homey.app/t/app-pro-python-script/157001/8 "2026-07-29T13:21:47Z")

</div>

and its live
