diff --git a/Makefile b/Makefile
index 25da6c41..fcd53e2f 100644
--- a/Makefile
+++ b/Makefile
@@ -1,4 +1,4 @@
-PKGS = balance float refloat tnt vbms32 vbms32_micro
+PKGS = balance float refloat tnt vbms32 vbms32_micro timeout
PKGS += lib_files lib_interpolation lib_nau7802 lib_pn532
PKGS += lib_ws2812 logui lib_code_server lib_midi lib_disp_ui
PKGS += vdisp lib_tca9535 vbms_harmony32
diff --git a/res_all.qrc b/res_all.qrc
index 58dd9c17..866fa20a 100644
--- a/res_all.qrc
+++ b/res_all.qrc
@@ -20,6 +20,7 @@
vdisp/vdisp.vescpkg
vdisp/vdisp_esc.vescpkg
vbms_harmony32/vbms_harmony32.vescpkg
+ timeout/timeout.vescpkg
diff --git a/timeout/Makefile b/timeout/Makefile
new file mode 100644
index 00000000..2ae5c22a
--- /dev/null
+++ b/timeout/Makefile
@@ -0,0 +1,18 @@
+VESC_TOOL ?= vesc_tool
+OLDVT ?= 0
+
+all: timeout.vescpkg
+
+timeout.vescpkg: timeout.lisp README.md pkgdesc.qml
+ifeq ($(OLDVT), 1)
+ $(VESC_TOOL) --buildPkg "timeout.vescpkg:timeout.lisp::0:README.md:Remote Timeout"
+else
+ $(VESC_TOOL) --buildPkgFromDesc pkgdesc.qml --testPkgDesc 'custom:test' --testPkgDesc 'vesc:test'
+endif
+
+clean:
+ rm -f timeout.vescpkg
+
+.PHONY: all clean
+
+
diff --git a/timeout/README.md b/timeout/README.md
new file mode 100644
index 00000000..0fc8d6bf
--- /dev/null
+++ b/timeout/README.md
@@ -0,0 +1,22 @@
+# Remote Timeout
+
+A simple safety script for VESC-based ESCs that do not properly handle remote disconnect timeouts. If the remote input stops updating for 1.00 s, motor current is set to zero.
+
+## What it does
+
+- Monitors the age of the last received remote input using `get-remote-state`.
+- If the age exceeds 1.00 s, commands zero current to stop the motor.
+- Runs at a low cadence to minimize load.
+
+## Usage
+
+1. Install the package from the VESC Tool package store.
+2. Start the package once from the Packages page to save it.
+3. After that it runs at boot automatically. The timeout is fixed to 1.00 s.
+
+## Compatibility
+
+- Works on VESC-based ESCs that support packages and expose `get-remote-state`.
+- Not compatible with the classic VESC BMS.
+
+
\ No newline at end of file
diff --git a/timeout/pkgdesc.qml b/timeout/pkgdesc.qml
new file mode 100644
index 00000000..1ba917fe
--- /dev/null
+++ b/timeout/pkgdesc.qml
@@ -0,0 +1,32 @@
+import QtQuick 2.15
+
+Item {
+ property string pkgName: "Remote Timeout"
+ property string pkgDescriptionMd: "README.md"
+ property string pkgLisp: "timeout.lisp"
+ property string pkgQml: ""
+ property bool pkgQmlIsFullscreen: false
+ property string pkgOutput: "timeout.vescpkg"
+
+ // This function should return true when this package is compatible
+ // with the connected vesc-based device
+ function isCompatible (fwRxParams) {
+ var hwName = fwRxParams.hw.toLowerCase();
+ var fwName = fwRxParams.fwName.toLowerCase();
+ var hwType = fwRxParams.hwTypeStr().toLowerCase();
+
+ // The classic VESC BMS does not support packages at all
+ if (hwType == "vesc bms") {
+ return false
+ }
+
+ // Works on vesc-based ESCs only
+ if (hwType != "vesc") {
+ return false
+ }
+
+ return true
+ }
+}
+
+
diff --git a/timeout/timeout.lisp b/timeout/timeout.lisp
new file mode 100644
index 00000000..d0b09bc5
--- /dev/null
+++ b/timeout/timeout.lisp
@@ -0,0 +1,27 @@
+; Remote timeout safety feature
+@const-start
+(def remote_drop_s 1.00) ; fixed timeout (s)
+(def loop_dt_s 0.02) ; loop cadence (s)
+@const-end
+
+(def mote-age 0.0)
+(def state nil)
+(def age-val 0.0)
+
+(defun main () (loopwhile t {
+ (def state (get-remote-state)) ; (js-y js-x bt-c bt-z is-rev update-age)
+
+ (def age-val (ix state 5))
+ (def mote-age (if age-val age-val 9999.0))
+
+ ; if age > threshold ? zero current
+ (if (> mote-age remote_drop_s)
+ (set-current 0 0.05)
+ 0)
+
+ (sleep loop_dt_s)
+}))
+
+(trap (image-save))
+(main)
+