diff --git a/applications/ibutton/ibutton.c b/applications/ibutton/ibutton.c
index 30accd46..5ccb1f6c 100644
--- a/applications/ibutton/ibutton.c
+++ b/applications/ibutton/ibutton.c
@@ -5,7 +5,7 @@
 #include "m-string.h"
 #include <toolbox/path.h>
 #include <flipper_format/flipper_format.h>
-#include "rpc/rpc_app.h"
+#include <rpc/rpc_app.h>
 
 #define TAG "iButtonApp"
 
@@ -58,7 +58,7 @@ static void ibutton_make_app_folder(iButton* ibutton) {
     }
 }
 
-static bool ibutton_load_key_data(iButton* ibutton, string_t key_path, bool show_dialog) {
+bool ibutton_load_key_data(iButton* ibutton, string_t key_path, bool show_dialog) {
     FlipperFormat* file = flipper_format_file_alloc(ibutton->storage);
     bool result = false;
     string_t data;
@@ -99,33 +99,20 @@ static bool ibutton_load_key_data(iButton* ibutton, string_t key_path, bool show
     return result;
 }
 
-static bool ibutton_rpc_command_callback(RpcAppSystemEvent event, const char* arg, void* context) {
+static void ibutton_rpc_command_callback(RpcAppSystemEvent event, void* context) {
     furi_assert(context);
     iButton* ibutton = context;
 
-    bool result = false;
-
     if(event == RpcAppEventSessionClose) {
-        rpc_system_app_set_callback(ibutton->rpc_ctx, NULL, NULL);
-        ibutton->rpc_ctx = NULL;
-        view_dispatcher_send_custom_event(ibutton->view_dispatcher, iButtonCustomEventRpcExit);
-        result = true;
+        view_dispatcher_send_custom_event(
+            ibutton->view_dispatcher, iButtonCustomEventRpcSessionClose);
     } else if(event == RpcAppEventAppExit) {
         view_dispatcher_send_custom_event(ibutton->view_dispatcher, iButtonCustomEventRpcExit);
-        result = true;
     } else if(event == RpcAppEventLoadFile) {
-        if(arg) {
-            string_set_str(ibutton->file_path, arg);
-            if(ibutton_load_key_data(ibutton, ibutton->file_path, false)) {
-                ibutton_worker_emulate_start(ibutton->key_worker, ibutton->key);
-                view_dispatcher_send_custom_event(
-                    ibutton->view_dispatcher, iButtonCustomEventRpcLoad);
-                result = true;
-            }
-        }
+        view_dispatcher_send_custom_event(ibutton->view_dispatcher, iButtonCustomEventRpcLoad);
+    } else {
+        rpc_system_app_confirm(ibutton->rpc_ctx, event, false);
     }
-
-    return result;
 }
 
 bool ibutton_custom_event_callback(void* context, uint32_t event) {
diff --git a/applications/ibutton/ibutton_custom_event.h b/applications/ibutton/ibutton_custom_event.h
index 25dfc31d..1e2f0300 100644
--- a/applications/ibutton/ibutton_custom_event.h
+++ b/applications/ibutton/ibutton_custom_event.h
@@ -12,4 +12,5 @@ enum iButtonCustomEvent {
 
     iButtonCustomEventRpcLoad,
     iButtonCustomEventRpcExit,
+    iButtonCustomEventRpcSessionClose,
 };
diff --git a/applications/ibutton/ibutton_i.h b/applications/ibutton/ibutton_i.h
index de3065c3..9d4354d0 100644
--- a/applications/ibutton/ibutton_i.h
+++ b/applications/ibutton/ibutton_i.h
@@ -78,6 +78,7 @@ typedef enum {
 } iButtonNotificationMessage;
 
 bool ibutton_file_select(iButton* ibutton);
+bool ibutton_load_key_data(iButton* ibutton, string_t key_path, bool show_dialog);
 bool ibutton_save_key(iButton* ibutton, const char* key_name);
 bool ibutton_delete_key(iButton* ibutton);
 void ibutton_text_store_set(iButton* ibutton, const char* text, ...);
diff --git a/applications/ibutton/scenes/ibutton_scene_rpc.c b/applications/ibutton/scenes/ibutton_scene_rpc.c
index 14f7df63..a3f5eeee 100644
--- a/applications/ibutton/scenes/ibutton_scene_rpc.c
+++ b/applications/ibutton/scenes/ibutton_scene_rpc.c
@@ -1,5 +1,6 @@
 #include "../ibutton_i.h"
 #include <toolbox/path.h>
+#include <rpc/rpc_app.h>
 
 void ibutton_scene_rpc_on_enter(void* context) {
     iButton* ibutton = context;
@@ -26,23 +27,40 @@ bool ibutton_scene_rpc_on_event(void* context, SceneManagerEvent event) {
     if(event.type == SceneManagerEventTypeCustom) {
         consumed = true;
         if(event.event == iButtonCustomEventRpcLoad) {
-            string_t key_name;
-            string_init(key_name);
-            if(string_end_with_str_p(ibutton->file_path, IBUTTON_APP_EXTENSION)) {
-                path_extract_filename(ibutton->file_path, key_name, true);
+            const char* arg = rpc_system_app_get_data(ibutton->rpc_ctx);
+            bool result = false;
+            if(arg) {
+                string_set_str(ibutton->file_path, arg);
+                if(ibutton_load_key_data(ibutton, ibutton->file_path, false)) {
+                    ibutton_worker_emulate_start(ibutton->key_worker, ibutton->key);
+                    string_t key_name;
+                    string_init(key_name);
+                    if(string_end_with_str_p(ibutton->file_path, IBUTTON_APP_EXTENSION)) {
+                        path_extract_filename(ibutton->file_path, key_name, true);
+                    }
+
+                    if(!string_empty_p(key_name)) {
+                        ibutton_text_store_set(
+                            ibutton, "emulating\n%s", string_get_cstr(key_name));
+                    } else {
+                        ibutton_text_store_set(ibutton, "emulating");
+                    }
+                    popup_set_text(popup, ibutton->text_store, 82, 32, AlignCenter, AlignTop);
+
+                    ibutton_notification_message(ibutton, iButtonNotificationMessageEmulateStart);
+
+                    string_clear(key_name);
+                    result = true;
+                }
             }
-
-            if(!string_empty_p(key_name)) {
-                ibutton_text_store_set(ibutton, "emulating\n%s", string_get_cstr(key_name));
-            } else {
-                ibutton_text_store_set(ibutton, "emulating");
-            }
-            popup_set_text(popup, ibutton->text_store, 82, 32, AlignCenter, AlignTop);
-
-            ibutton_notification_message(ibutton, iButtonNotificationMessageEmulateStart);
-
-            string_clear(key_name);
+            rpc_system_app_confirm(ibutton->rpc_ctx, RpcAppEventLoadFile, result);
         } else if(event.event == iButtonCustomEventRpcExit) {
+            rpc_system_app_confirm(ibutton->rpc_ctx, RpcAppEventAppExit, true);
+            ibutton_notification_message(ibutton, iButtonNotificationMessageBlinkStop);
+            view_dispatcher_stop(ibutton->view_dispatcher);
+        } else if(event.event == iButtonCustomEventRpcSessionClose) {
+            rpc_system_app_set_callback(ibutton->rpc_ctx, NULL, NULL);
+            ibutton->rpc_ctx = NULL;
             ibutton_notification_message(ibutton, iButtonNotificationMessageBlinkStop);
             view_dispatcher_stop(ibutton->view_dispatcher);
         }
diff --git a/applications/infrared/infrared.c b/applications/infrared/infrared.c
index 4b7a4671..cbbd375d 100644
--- a/applications/infrared/infrared.c
+++ b/applications/infrared/infrared.c
@@ -36,52 +36,29 @@ static void infrared_tick_event_callback(void* context) {
     scene_manager_handle_tick_event(infrared->scene_manager);
 }
 
-static bool
-    infrared_rpc_command_callback(RpcAppSystemEvent event, const char* arg, void* context) {
+static void infrared_rpc_command_callback(RpcAppSystemEvent event, void* context) {
     furi_assert(context);
     Infrared* infrared = context;
-
-    if(!infrared->rpc_ctx) {
-        return false;
-    }
-
-    bool result = false;
+    furi_assert(infrared->rpc_ctx);
 
     if(event == RpcAppEventSessionClose) {
-        rpc_system_app_set_callback(infrared->rpc_ctx, NULL, NULL);
-        infrared->rpc_ctx = NULL;
         view_dispatcher_send_custom_event(
-            infrared->view_dispatcher, InfraredCustomEventTypeBackPressed);
-        result = true;
+            infrared->view_dispatcher, InfraredCustomEventTypeRpcSessionClose);
     } else if(event == RpcAppEventAppExit) {
         view_dispatcher_send_custom_event(
-            infrared->view_dispatcher, InfraredCustomEventTypeBackPressed);
-        result = true;
+            infrared->view_dispatcher, InfraredCustomEventTypeRpcExit);
     } else if(event == RpcAppEventLoadFile) {
-        if(arg) {
-            string_set_str(infrared->file_path, arg);
-            result = infrared_remote_load(infrared->remote, infrared->file_path);
-            infrared_worker_tx_set_get_signal_callback(
-                infrared->worker, infrared_worker_tx_get_signal_steady_callback, infrared);
-            infrared_worker_tx_set_signal_sent_callback(
-                infrared->worker, infrared_signal_sent_callback, infrared);
-            view_dispatcher_send_custom_event(
-                infrared->view_dispatcher, InfraredCustomEventTypeRpcLoaded);
-        }
+        view_dispatcher_send_custom_event(
+            infrared->view_dispatcher, InfraredCustomEventTypeRpcLoad);
     } else if(event == RpcAppEventButtonPress) {
-        if(arg) {
-            size_t button_index = 0;
-            if(infrared_remote_find_button_by_name(infrared->remote, arg, &button_index)) {
-                infrared_tx_start_button_index(infrared, button_index);
-                result = true;
-            }
-        }
+        view_dispatcher_send_custom_event(
+            infrared->view_dispatcher, InfraredCustomEventTypeRpcButtonPress);
     } else if(event == RpcAppEventButtonRelease) {
-        infrared_tx_stop(infrared);
-        result = true;
+        view_dispatcher_send_custom_event(
+            infrared->view_dispatcher, InfraredCustomEventTypeRpcButtonRelease);
+    } else {
+        rpc_system_app_confirm(infrared->rpc_ctx, event, false);
     }
-
-    return result;
 }
 
 static void infrared_find_vacant_remote_name(string_t name, const char* path) {
diff --git a/applications/infrared/infrared_custom_event.h b/applications/infrared/infrared_custom_event.h
index 29bd61f1..09440dde 100644
--- a/applications/infrared/infrared_custom_event.h
+++ b/applications/infrared/infrared_custom_event.h
@@ -14,7 +14,12 @@ enum InfraredCustomEventType {
     InfraredCustomEventTypePopupClosed,
     InfraredCustomEventTypeButtonSelected,
     InfraredCustomEventTypeBackPressed,
-    InfraredCustomEventTypeRpcLoaded,
+
+    InfraredCustomEventTypeRpcLoad,
+    InfraredCustomEventTypeRpcExit,
+    InfraredCustomEventTypeRpcButtonPress,
+    InfraredCustomEventTypeRpcButtonRelease,
+    InfraredCustomEventTypeRpcSessionClose,
 };
 
 #pragma pack(push, 1)
diff --git a/applications/infrared/scenes/infrared_scene_rpc.c b/applications/infrared/scenes/infrared_scene_rpc.c
index e31e7fb6..1d970f6a 100644
--- a/applications/infrared/scenes/infrared_scene_rpc.c
+++ b/applications/infrared/scenes/infrared_scene_rpc.c
@@ -28,12 +28,45 @@ bool infrared_scene_rpc_on_event(void* context, SceneManagerEvent event) {
             view_dispatcher_stop(infrared->view_dispatcher);
         } else if(event.event == InfraredCustomEventTypePopupClosed) {
             view_dispatcher_stop(infrared->view_dispatcher);
-        } else if(event.event == InfraredCustomEventTypeRpcLoaded) {
+        } else if(event.event == InfraredCustomEventTypeRpcLoad) {
+            bool result = false;
+            const char* arg = rpc_system_app_get_data(infrared->rpc_ctx);
+            if(arg) {
+                string_set_str(infrared->file_path, arg);
+                result = infrared_remote_load(infrared->remote, infrared->file_path);
+                infrared_worker_tx_set_get_signal_callback(
+                    infrared->worker, infrared_worker_tx_get_signal_steady_callback, infrared);
+                infrared_worker_tx_set_signal_sent_callback(
+                    infrared->worker, infrared_signal_sent_callback, infrared);
+            }
             const char* remote_name = infrared_remote_get_name(infrared->remote);
 
             infrared_text_store_set(infrared, 0, "loaded\n%s", remote_name);
             popup_set_text(
                 infrared->popup, infrared->text_store[0], 82, 32, AlignCenter, AlignTop);
+
+            rpc_system_app_confirm(infrared->rpc_ctx, RpcAppEventLoadFile, result);
+        } else if(event.event == InfraredCustomEventTypeRpcButtonPress) {
+            bool result = false;
+            const char* arg = rpc_system_app_get_data(infrared->rpc_ctx);
+            if(arg) {
+                size_t button_index = 0;
+                if(infrared_remote_find_button_by_name(infrared->remote, arg, &button_index)) {
+                    infrared_tx_start_button_index(infrared, button_index);
+                    result = true;
+                }
+            }
+            rpc_system_app_confirm(infrared->rpc_ctx, RpcAppEventButtonRelease, result);
+        } else if(event.event == InfraredCustomEventTypeRpcButtonRelease) {
+            infrared_tx_stop(infrared);
+            rpc_system_app_confirm(infrared->rpc_ctx, RpcAppEventButtonRelease, true);
+        } else if(event.event == InfraredCustomEventTypeRpcExit) {
+            view_dispatcher_stop(infrared->view_dispatcher);
+            rpc_system_app_confirm(infrared->rpc_ctx, RpcAppEventAppExit, true);
+        } else if(event.event == InfraredCustomEventTypeRpcSessionClose) {
+            rpc_system_app_set_callback(infrared->rpc_ctx, NULL, NULL);
+            infrared->rpc_ctx = NULL;
+            view_dispatcher_stop(infrared->view_dispatcher);
         }
     }
     return consumed;
diff --git a/applications/lfrfid/lfrfid_app.cpp b/applications/lfrfid/lfrfid_app.cpp
index 329f052b..29e99b74 100644
--- a/applications/lfrfid/lfrfid_app.cpp
+++ b/applications/lfrfid/lfrfid_app.cpp
@@ -25,7 +25,7 @@
 #include <toolbox/path.h>
 #include <flipper_format/flipper_format.h>
 
-#include "rpc/rpc_app.h"
+#include <rpc/rpc_app.h>
 
 const char* LfRfidApp::app_folder = ANY_PATH("lfrfid");
 const char* LfRfidApp::app_extension = ".rfid";
@@ -48,38 +48,25 @@ LfRfidApp::~LfRfidApp() {
     }
 }
 
-static bool rpc_command_callback(RpcAppSystemEvent event, const char* arg, void* context) {
+static void rpc_command_callback(RpcAppSystemEvent rpc_event, void* context) {
     furi_assert(context);
     LfRfidApp* app = static_cast<LfRfidApp*>(context);
 
-    bool result = false;
-
-    if(event == RpcAppEventSessionClose) {
-        rpc_system_app_set_callback(app->rpc_ctx, NULL, NULL);
-        app->rpc_ctx = NULL;
+    if(rpc_event == RpcAppEventSessionClose) {
+        LfRfidApp::Event event;
+        event.type = LfRfidApp::EventType::RpcSessionClose;
+        app->view_controller.send_event(&event);
+    } else if(rpc_event == RpcAppEventAppExit) {
         LfRfidApp::Event event;
         event.type = LfRfidApp::EventType::Exit;
         app->view_controller.send_event(&event);
-        result = true;
-    } else if(event == RpcAppEventAppExit) {
+    } else if(rpc_event == RpcAppEventLoadFile) {
         LfRfidApp::Event event;
-        event.type = LfRfidApp::EventType::Exit;
+        event.type = LfRfidApp::EventType::RpcLoadFile;
         app->view_controller.send_event(&event);
-        result = true;
-    } else if(event == RpcAppEventLoadFile) {
-        if(arg) {
-            string_set_str(app->file_path, arg);
-            if(app->load_key_data(app->file_path, &(app->worker.key), false)) {
-                LfRfidApp::Event event;
-                event.type = LfRfidApp::EventType::EmulateStart;
-                app->view_controller.send_event(&event);
-                app->worker.start_emulate();
-                result = true;
-            }
-        }
+    } else {
+        rpc_system_app_confirm(app->rpc_ctx, rpc_event, false);
     }
-
-    return result;
 }
 
 void LfRfidApp::run(void* _args) {
diff --git a/applications/lfrfid/lfrfid_app.h b/applications/lfrfid/lfrfid_app.h
index 3372552f..b0d4c589 100644
--- a/applications/lfrfid/lfrfid_app.h
+++ b/applications/lfrfid/lfrfid_app.h
@@ -33,6 +33,8 @@ public:
         Retry,
         Exit,
         EmulateStart,
+        RpcLoadFile,
+        RpcSessionClose,
     };
 
     enum class SceneType : uint8_t {
diff --git a/applications/lfrfid/scene/lfrfid_app_scene_rpc.cpp b/applications/lfrfid/scene/lfrfid_app_scene_rpc.cpp
index bc070ce6..a32982af 100644
--- a/applications/lfrfid/scene/lfrfid_app_scene_rpc.cpp
+++ b/applications/lfrfid/scene/lfrfid_app_scene_rpc.cpp
@@ -1,6 +1,7 @@
 #include "lfrfid_app_scene_rpc.h"
 #include <core/common_defines.h>
 #include <dolphin/dolphin.h>
+#include <rpc/rpc_app.h>
 
 static const NotificationSequence sequence_blink_start_magenta = {
     &message_blink_start_10,
@@ -36,6 +37,16 @@ bool LfRfidAppSceneRpc::on_event(LfRfidApp* app, LfRfidApp::Event* event) {
         LfRfidApp::Event view_event;
         view_event.type = LfRfidApp::EventType::Back;
         app->view_controller.send_event(&view_event);
+        rpc_system_app_confirm(app->rpc_ctx, RpcAppEventAppExit, true);
+    } else if(event->type == LfRfidApp::EventType::RpcSessionClose) {
+        // Detach RPC
+        rpc_system_app_set_callback(app->rpc_ctx, NULL, NULL);
+        app->rpc_ctx = NULL;
+
+        consumed = true;
+        LfRfidApp::Event view_event;
+        view_event.type = LfRfidApp::EventType::Back;
+        app->view_controller.send_event(&view_event);
     } else if(event->type == LfRfidApp::EventType::EmulateStart) {
         auto popup = app->view_controller.get<PopupVM>();
         consumed = true;
@@ -45,7 +56,22 @@ bool LfRfidAppSceneRpc::on_event(LfRfidApp* app, LfRfidApp::Event* event) {
         popup->set_text(app->text_store.text, 89, 43, AlignCenter, AlignTop);
 
         notification_message(app->notification, &sequence_blink_start_magenta);
+    } else if(event->type == LfRfidApp::EventType::RpcLoadFile) {
+        const char* arg = rpc_system_app_get_data(app->rpc_ctx);
+        bool result = false;
+        if(arg) {
+            string_set_str(app->file_path, arg);
+            if(app->load_key_data(app->file_path, &(app->worker.key), false)) {
+                LfRfidApp::Event event;
+                event.type = LfRfidApp::EventType::EmulateStart;
+                app->view_controller.send_event(&event);
+                app->worker.start_emulate();
+                result = true;
+            }
+        }
+        rpc_system_app_confirm(app->rpc_ctx, RpcAppEventLoadFile, result);
     }
+
     return consumed;
 }
 
diff --git a/applications/nfc/helpers/nfc_custom_event.h b/applications/nfc/helpers/nfc_custom_event.h
index fbd54b27..4227a5b1 100644
--- a/applications/nfc/helpers/nfc_custom_event.h
+++ b/applications/nfc/helpers/nfc_custom_event.h
@@ -11,4 +11,5 @@ enum NfcCustomEvent {
     NfcCustomEventDictAttackDone,
     NfcCustomEventDictAttackSkip,
     NfcCustomEventRpcLoad,
+    NfcCustomEventRpcSessionClose,
 };
diff --git a/applications/nfc/nfc.c b/applications/nfc/nfc.c
index b19f92f2..32e74e8f 100644
--- a/applications/nfc/nfc.c
+++ b/applications/nfc/nfc.c
@@ -13,78 +13,21 @@ bool nfc_back_event_callback(void* context) {
     return scene_manager_handle_back_event(nfc->scene_manager);
 }
 
-void nfc_rpc_exit_callback(Nfc* nfc) {
-    if(nfc->rpc_state == NfcRpcStateEmulating) {
-        // Stop worker
-        nfc_worker_stop(nfc->worker);
-    } else if(nfc->rpc_state == NfcRpcStateEmulated) {
-        // Stop worker
-        nfc_worker_stop(nfc->worker);
-        // Save data in shadow file
-        nfc_device_save_shadow(nfc->dev, nfc->dev->dev_name);
-    }
-    if(nfc->rpc_ctx) {
-        rpc_system_app_set_callback(nfc->rpc_ctx, NULL, NULL);
-        rpc_system_app_send_exited(nfc->rpc_ctx);
-        nfc->rpc_ctx = NULL;
-    }
-}
-
-static bool nfc_rpc_emulate_callback(NfcWorkerEvent event, void* context) {
-    UNUSED(event);
-    Nfc* nfc = context;
-
-    nfc->rpc_state = NfcRpcStateEmulated;
-    return true;
-}
-
-static bool nfc_rpc_command_callback(RpcAppSystemEvent event, const char* arg, void* context) {
+static void nfc_rpc_command_callback(RpcAppSystemEvent event, void* context) {
     furi_assert(context);
     Nfc* nfc = context;
 
-    if(!nfc->rpc_ctx) {
-        return false;
-    }
-
-    bool result = false;
+    furi_assert(nfc->rpc_ctx);
 
     if(event == RpcAppEventSessionClose) {
-        rpc_system_app_set_callback(nfc->rpc_ctx, NULL, NULL);
-        nfc->rpc_ctx = NULL;
-        view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventViewExit);
-        result = true;
+        view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventRpcSessionClose);
     } else if(event == RpcAppEventAppExit) {
         view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventViewExit);
-        result = true;
     } else if(event == RpcAppEventLoadFile) {
-        if((arg) && (nfc->rpc_state == NfcRpcStateIdle)) {
-            if(nfc_device_load(nfc->dev, arg, false)) {
-                if(nfc->dev->format == NfcDeviceSaveFormatMifareUl) {
-                    nfc_worker_start(
-                        nfc->worker,
-                        NfcWorkerStateMfUltralightEmulate,
-                        &nfc->dev->dev_data,
-                        nfc_rpc_emulate_callback,
-                        nfc);
-                } else if(nfc->dev->format == NfcDeviceSaveFormatMifareClassic) {
-                    nfc_worker_start(
-                        nfc->worker,
-                        NfcWorkerStateMfClassicEmulate,
-                        &nfc->dev->dev_data,
-                        nfc_rpc_emulate_callback,
-                        nfc);
-                } else {
-                    nfc_worker_start(
-                        nfc->worker, NfcWorkerStateUidEmulate, &nfc->dev->dev_data, NULL, nfc);
-                }
-                nfc->rpc_state = NfcRpcStateEmulating;
-                view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventRpcLoad);
-                result = true;
-            }
-        }
+        view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventRpcLoad);
+    } else {
+        rpc_system_app_confirm(nfc->rpc_ctx, event, false);
     }
-
-    return result;
 }
 
 Nfc* nfc_alloc() {
@@ -163,6 +106,21 @@ Nfc* nfc_alloc() {
 void nfc_free(Nfc* nfc) {
     furi_assert(nfc);
 
+    if(nfc->rpc_state == NfcRpcStateEmulating) {
+        // Stop worker
+        nfc_worker_stop(nfc->worker);
+    } else if(nfc->rpc_state == NfcRpcStateEmulated) {
+        // Stop worker
+        nfc_worker_stop(nfc->worker);
+        // Save data in shadow file
+        nfc_device_save_shadow(nfc->dev, nfc->dev->dev_name);
+    }
+    if(nfc->rpc_ctx) {
+        rpc_system_app_send_exited(nfc->rpc_ctx);
+        rpc_system_app_set_callback(nfc->rpc_ctx, NULL, NULL);
+        nfc->rpc_ctx = NULL;
+    }
+
     // Nfc device
     nfc_device_free(nfc->dev);
 
diff --git a/applications/nfc/nfc_i.h b/applications/nfc/nfc_i.h
index 84c0e7f0..5a916e80 100755
--- a/applications/nfc/nfc_i.h
+++ b/applications/nfc/nfc_i.h
@@ -102,5 +102,3 @@ void nfc_blink_start(Nfc* nfc);
 void nfc_blink_stop(Nfc* nfc);
 
 void nfc_show_loading_popup(void* context, bool show);
-
-void nfc_rpc_exit_callback(Nfc* nfc);
diff --git a/applications/nfc/scenes/nfc_scene_rpc.c b/applications/nfc/scenes/nfc_scene_rpc.c
index 582dff8e..94beccc6 100644
--- a/applications/nfc/scenes/nfc_scene_rpc.c
+++ b/applications/nfc/scenes/nfc_scene_rpc.c
@@ -14,6 +14,14 @@ void nfc_scene_rpc_on_enter(void* context) {
     notification_message(nfc->notifications, &sequence_display_backlight_on);
 }
 
+static bool nfc_scene_rpc_emulate_callback(NfcWorkerEvent event, void* context) {
+    UNUSED(event);
+    Nfc* nfc = context;
+
+    nfc->rpc_state = NfcRpcStateEmulated;
+    return true;
+}
+
 bool nfc_scene_rpc_on_event(void* context, SceneManagerEvent event) {
     Nfc* nfc = context;
     Popup* popup = nfc->popup;
@@ -22,13 +30,47 @@ bool nfc_scene_rpc_on_event(void* context, SceneManagerEvent event) {
     if(event.type == SceneManagerEventTypeCustom) {
         consumed = true;
         if(event.event == NfcCustomEventViewExit) {
+            rpc_system_app_confirm(nfc->rpc_ctx, RpcAppEventAppExit, true);
+            view_dispatcher_stop(nfc->view_dispatcher);
+            nfc_blink_stop(nfc);
+        } else if(event.event == NfcCustomEventRpcSessionClose) {
+            rpc_system_app_set_callback(nfc->rpc_ctx, NULL, NULL);
+            nfc->rpc_ctx = NULL;
             view_dispatcher_stop(nfc->view_dispatcher);
             nfc_blink_stop(nfc);
         } else if(event.event == NfcCustomEventRpcLoad) {
-            nfc_blink_start(nfc);
+            bool result = false;
+            const char* arg = rpc_system_app_get_data(nfc->rpc_ctx);
+            if((arg) && (nfc->rpc_state == NfcRpcStateIdle)) {
+                if(nfc_device_load(nfc->dev, arg, false)) {
+                    if(nfc->dev->format == NfcDeviceSaveFormatMifareUl) {
+                        nfc_worker_start(
+                            nfc->worker,
+                            NfcWorkerStateMfUltralightEmulate,
+                            &nfc->dev->dev_data,
+                            nfc_scene_rpc_emulate_callback,
+                            nfc);
+                    } else if(nfc->dev->format == NfcDeviceSaveFormatMifareClassic) {
+                        nfc_worker_start(
+                            nfc->worker,
+                            NfcWorkerStateMfClassicEmulate,
+                            &nfc->dev->dev_data,
+                            nfc_scene_rpc_emulate_callback,
+                            nfc);
+                    } else {
+                        nfc_worker_start(
+                            nfc->worker, NfcWorkerStateUidEmulate, &nfc->dev->dev_data, NULL, nfc);
+                    }
+                    nfc->rpc_state = NfcRpcStateEmulating;
+                    result = true;
 
-            nfc_text_store_set(nfc, "emulating\n%s", nfc->dev->dev_name);
-            popup_set_text(popup, nfc->text_store, 82, 32, AlignCenter, AlignTop);
+                    nfc_blink_start(nfc);
+                    nfc_text_store_set(nfc, "emulating\n%s", nfc->dev->dev_name);
+                    popup_set_text(popup, nfc->text_store, 82, 32, AlignCenter, AlignTop);
+                }
+            }
+
+            rpc_system_app_confirm(nfc->rpc_ctx, RpcAppEventLoadFile, result);
         }
     }
     return consumed;
@@ -38,7 +80,6 @@ void nfc_scene_rpc_on_exit(void* context) {
     Nfc* nfc = context;
     Popup* popup = nfc->popup;
 
-    nfc_rpc_exit_callback(nfc);
     nfc_blink_stop(nfc);
 
     popup_set_header(popup, NULL, 0, 0, AlignCenter, AlignBottom);
diff --git a/applications/rpc/rpc_app.c b/applications/rpc/rpc_app.c
index e349e61c..555cec8c 100644
--- a/applications/rpc/rpc_app.c
+++ b/applications/rpc/rpc_app.c
@@ -6,24 +6,18 @@
 #include "rpc_app.h"
 
 #define TAG "RpcSystemApp"
-#define APP_BUTTON_TIMEOUT 1000
 
 struct RpcAppSystem {
     RpcSession* session;
     RpcAppSystemCallback app_callback;
     void* app_context;
     PB_Main* state_msg;
-    FuriTimer* timer;
+
+    uint32_t last_id;
+    char* last_data;
 };
 
-static void rpc_system_app_timer_callback(void* context) {
-    furi_assert(context);
-    RpcAppSystem* rpc_app = context;
-
-    if(rpc_app->app_callback) {
-        rpc_app->app_callback(RpcAppEventButtonRelease, NULL, rpc_app->app_context);
-    }
-}
+#define RPC_SYSTEM_APP_TEMP_ARGS_SIZE 16
 
 static void rpc_system_app_start_process(const PB_Main* request, void* context) {
     furi_assert(request);
@@ -33,9 +27,12 @@ static void rpc_system_app_start_process(const PB_Main* request, void* context)
     RpcAppSystem* rpc_app = context;
     RpcSession* session = rpc_app->session;
     furi_assert(session);
-    char args_temp[16];
+    char args_temp[RPC_SYSTEM_APP_TEMP_ARGS_SIZE];
 
-    FURI_LOG_D(TAG, "Start");
+    furi_assert(!rpc_app->last_id);
+    furi_assert(!rpc_app->last_data);
+
+    FURI_LOG_D(TAG, "StartProcess: id %d", request->command_id);
 
     PB_CommandStatus result = PB_CommandStatus_ERROR_APP_CANT_START;
 
@@ -43,9 +40,9 @@ static void rpc_system_app_start_process(const PB_Main* request, void* context)
     const char* app_name = request->content.app_start_request.name;
     if(app_name) {
         const char* app_args = request->content.app_start_request.args;
-        if(strcmp(app_args, "RPC") == 0) {
+        if(app_args && strcmp(app_args, "RPC") == 0) {
             // If app is being started in RPC mode - pass RPC context via args string
-            snprintf(args_temp, 16, "RPC %08lX", (uint32_t)rpc_app);
+            snprintf(args_temp, RPC_SYSTEM_APP_TEMP_ARGS_SIZE, "RPC %08lX", (uint32_t)rpc_app);
             app_args = args_temp;
         }
         LoaderStatus status = loader_start(loader, app_name, app_args);
@@ -58,7 +55,7 @@ static void rpc_system_app_start_process(const PB_Main* request, void* context)
         } else if(status == LoaderStatusOk) {
             result = PB_CommandStatus_OK;
         } else {
-            furi_assert(0);
+            furi_crash("Programming Error");
         }
     } else {
         result = PB_CommandStatus_ERROR_INVALID_PARAMETERS;
@@ -66,6 +63,7 @@ static void rpc_system_app_start_process(const PB_Main* request, void* context)
 
     furi_record_close(RECORD_LOADER);
 
+    FURI_LOG_D(TAG, "StartProcess: response id %d, result %d", request->command_id, result);
     rpc_send_and_release_empty(session, request->command_id, result);
 }
 
@@ -93,6 +91,7 @@ static void rpc_system_app_lock_status_process(const PB_Main* request, void* con
 
     furi_record_close(RECORD_LOADER);
 
+    FURI_LOG_D(TAG, "LockStatus: response");
     rpc_send_and_release(session, &response);
     pb_release(&PB_Main_msg, &response);
 }
@@ -109,17 +108,17 @@ static void rpc_system_app_exit_request(const PB_Main* request, void* context) {
     PB_CommandStatus status;
 
     if(rpc_app->app_callback) {
-        if(rpc_app->app_callback(RpcAppEventAppExit, NULL, rpc_app->app_context)) {
-            status = PB_CommandStatus_OK;
-            furi_timer_stop(rpc_app->timer);
-        } else {
-            status = PB_CommandStatus_ERROR_APP_CMD_ERROR;
-        }
+        FURI_LOG_D(TAG, "ExitRequest: id %d", request->command_id);
+        furi_assert(!rpc_app->last_id);
+        furi_assert(!rpc_app->last_data);
+        rpc_app->last_id = request->command_id;
+        rpc_app->app_callback(RpcAppEventAppExit, rpc_app->app_context);
     } else {
         status = PB_CommandStatus_ERROR_APP_NOT_RUNNING;
+        FURI_LOG_E(
+            TAG, "ExitRequest: APP_NOT_RUNNING, id %d, status: %d", request->command_id, status);
+        rpc_send_and_release_empty(session, request->command_id, status);
     }
-
-    rpc_send_and_release_empty(session, request->command_id, status);
 }
 
 static void rpc_system_app_load_file(const PB_Main* request, void* context) {
@@ -133,17 +132,18 @@ static void rpc_system_app_load_file(const PB_Main* request, void* context) {
 
     PB_CommandStatus status;
     if(rpc_app->app_callback) {
-        const char* file_path = request->content.app_load_file_request.path;
-        if(rpc_app->app_callback(RpcAppEventLoadFile, file_path, rpc_app->app_context)) {
-            status = PB_CommandStatus_OK;
-        } else {
-            status = PB_CommandStatus_ERROR_APP_CMD_ERROR;
-        }
+        FURI_LOG_D(TAG, "LoadFile: id %d", request->command_id);
+        furi_assert(!rpc_app->last_id);
+        furi_assert(!rpc_app->last_data);
+        rpc_app->last_id = request->command_id;
+        rpc_app->last_data = strdup(request->content.app_load_file_request.path);
+        rpc_app->app_callback(RpcAppEventLoadFile, rpc_app->app_context);
     } else {
         status = PB_CommandStatus_ERROR_APP_NOT_RUNNING;
+        FURI_LOG_E(
+            TAG, "LoadFile: APP_NOT_RUNNING, id %d, status: %d", request->command_id, status);
+        rpc_send_and_release_empty(session, request->command_id, status);
     }
-
-    rpc_send_and_release_empty(session, request->command_id, status);
 }
 
 static void rpc_system_app_button_press(const PB_Main* request, void* context) {
@@ -157,18 +157,18 @@ static void rpc_system_app_button_press(const PB_Main* request, void* context) {
 
     PB_CommandStatus status;
     if(rpc_app->app_callback) {
-        const char* args = request->content.app_button_press_request.args;
-        if(rpc_app->app_callback(RpcAppEventButtonPress, args, rpc_app->app_context)) {
-            status = PB_CommandStatus_OK;
-            furi_timer_start(rpc_app->timer, APP_BUTTON_TIMEOUT);
-        } else {
-            status = PB_CommandStatus_ERROR_APP_CMD_ERROR;
-        }
+        FURI_LOG_D(TAG, "ButtonPress");
+        furi_assert(!rpc_app->last_id);
+        furi_assert(!rpc_app->last_data);
+        rpc_app->last_id = request->command_id;
+        rpc_app->last_data = strdup(request->content.app_button_press_request.args);
+        rpc_app->app_callback(RpcAppEventButtonPress, rpc_app->app_context);
     } else {
         status = PB_CommandStatus_ERROR_APP_NOT_RUNNING;
+        FURI_LOG_E(
+            TAG, "ButtonPress: APP_NOT_RUNNING, id %d, status: %d", request->command_id, status);
+        rpc_send_and_release_empty(session, request->command_id, status);
     }
-
-    rpc_send_and_release_empty(session, request->command_id, status);
 }
 
 static void rpc_system_app_button_release(const PB_Main* request, void* context) {
@@ -182,17 +182,17 @@ static void rpc_system_app_button_release(const PB_Main* request, void* context)
 
     PB_CommandStatus status;
     if(rpc_app->app_callback) {
-        if(rpc_app->app_callback(RpcAppEventButtonRelease, NULL, rpc_app->app_context)) {
-            status = PB_CommandStatus_OK;
-            furi_timer_stop(rpc_app->timer);
-        } else {
-            status = PB_CommandStatus_ERROR_APP_CMD_ERROR;
-        }
+        FURI_LOG_D(TAG, "ButtonRelease");
+        furi_assert(!rpc_app->last_id);
+        furi_assert(!rpc_app->last_data);
+        rpc_app->last_id = request->command_id;
+        rpc_app->app_callback(RpcAppEventButtonRelease, rpc_app->app_context);
     } else {
         status = PB_CommandStatus_ERROR_APP_NOT_RUNNING;
+        FURI_LOG_E(
+            TAG, "ButtonRelease: APP_NOT_RUNNING, id %d, status: %d", request->command_id, status);
+        rpc_send_and_release_empty(session, request->command_id, status);
     }
-
-    rpc_send_and_release_empty(session, request->command_id, status);
 }
 
 void rpc_system_app_send_started(RpcAppSystem* rpc_app) {
@@ -201,6 +201,8 @@ void rpc_system_app_send_started(RpcAppSystem* rpc_app) {
     furi_assert(session);
 
     rpc_app->state_msg->content.app_state_response.state = PB_App_AppState_APP_STARTED;
+
+    FURI_LOG_D(TAG, "SendStarted");
     rpc_send(session, rpc_app->state_msg);
 }
 
@@ -210,9 +212,46 @@ void rpc_system_app_send_exited(RpcAppSystem* rpc_app) {
     furi_assert(session);
 
     rpc_app->state_msg->content.app_state_response.state = PB_App_AppState_APP_CLOSED;
+
+    FURI_LOG_D(TAG, "SendExit");
     rpc_send(session, rpc_app->state_msg);
 }
 
+const char* rpc_system_app_get_data(RpcAppSystem* rpc_app) {
+    furi_assert(rpc_app);
+    furi_assert(rpc_app->last_data);
+    return rpc_app->last_data;
+}
+
+void rpc_system_app_confirm(RpcAppSystem* rpc_app, RpcAppSystemEvent event, bool result) {
+    furi_assert(rpc_app);
+    RpcSession* session = rpc_app->session;
+    furi_assert(session);
+    furi_assert(rpc_app->last_id);
+
+    PB_CommandStatus status = result ? PB_CommandStatus_OK : PB_CommandStatus_ERROR_APP_CMD_ERROR;
+
+    uint32_t last_id = 0;
+    switch(event) {
+    case RpcAppEventAppExit:
+    case RpcAppEventLoadFile:
+    case RpcAppEventButtonPress:
+    case RpcAppEventButtonRelease:
+        last_id = rpc_app->last_id;
+        rpc_app->last_id = 0;
+        if(rpc_app->last_data) {
+            free(rpc_app->last_data);
+            rpc_app->last_data = NULL;
+        }
+        FURI_LOG_D(TAG, "AppConfirm: event %d last_id %d status %d", event, last_id, status);
+        rpc_send_and_release_empty(session, last_id, status);
+        break;
+    default:
+        furi_crash("RPC App state programming Error");
+        break;
+    }
+}
+
 void rpc_system_app_set_callback(RpcAppSystem* rpc_app, RpcAppSystemCallback callback, void* ctx) {
     furi_assert(rpc_app);
 
@@ -226,8 +265,6 @@ void* rpc_system_app_alloc(RpcSession* session) {
     RpcAppSystem* rpc_app = malloc(sizeof(RpcAppSystem));
     rpc_app->session = session;
 
-    rpc_app->timer = furi_timer_alloc(rpc_system_app_timer_callback, FuriTimerTypeOnce, rpc_app);
-
     // App exit message
     rpc_app->state_msg = malloc(sizeof(PB_Main));
     rpc_app->state_msg->which_content = PB_Main_app_state_response_tag;
@@ -265,12 +302,16 @@ void rpc_system_app_free(void* context) {
     RpcSession* session = rpc_app->session;
     furi_assert(session);
 
-    furi_timer_free(rpc_app->timer);
-
     if(rpc_app->app_callback) {
-        rpc_app->app_callback(RpcAppEventSessionClose, NULL, rpc_app->app_context);
+        rpc_app->app_callback(RpcAppEventSessionClose, rpc_app->app_context);
     }
 
+    while(rpc_app->app_callback) {
+        furi_delay_tick(1);
+    }
+
+    if(rpc_app->last_data) free(rpc_app->last_data);
+
     free(rpc_app->state_msg);
     free(rpc_app);
 }
diff --git a/applications/rpc/rpc_app.h b/applications/rpc/rpc_app.h
index 4e00922f..635c9f8c 100644
--- a/applications/rpc/rpc_app.h
+++ b/applications/rpc/rpc_app.h
@@ -13,7 +13,7 @@ typedef enum {
     RpcAppEventButtonRelease,
 } RpcAppSystemEvent;
 
-typedef bool (*RpcAppSystemCallback)(RpcAppSystemEvent event, const char* arg, void* context);
+typedef void (*RpcAppSystemCallback)(RpcAppSystemEvent event, void* context);
 
 typedef struct RpcAppSystem RpcAppSystem;
 
@@ -23,6 +23,10 @@ void rpc_system_app_send_started(RpcAppSystem* rpc_app);
 
 void rpc_system_app_send_exited(RpcAppSystem* rpc_app);
 
+const char* rpc_system_app_get_data(RpcAppSystem* rpc_app);
+
+void rpc_system_app_confirm(RpcAppSystem* rpc_app, RpcAppSystemEvent event, bool result);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/applications/subghz/helpers/subghz_custom_event.h b/applications/subghz/helpers/subghz_custom_event.h
index 801a8ae9..765c9e25 100644
--- a/applications/subghz/helpers/subghz_custom_event.h
+++ b/applications/subghz/helpers/subghz_custom_event.h
@@ -47,6 +47,9 @@ typedef enum {
     SubGhzCustomEventSceneStay,
 
     SubGhzCustomEventSceneRpcLoad,
+    SubGhzCustomEventSceneRpcButtonPress,
+    SubGhzCustomEventSceneRpcButtonRelease,
+    SubGhzCustomEventSceneRpcSessionClose,
 
     SubGhzCustomEventViewReceiverOK,
     SubGhzCustomEventViewReceiverConfig,
diff --git a/applications/subghz/scenes/subghz_scene_rpc.c b/applications/subghz/scenes/subghz_scene_rpc.c
index 844f5c16..c6f7df26 100644
--- a/applications/subghz/scenes/subghz_scene_rpc.c
+++ b/applications/subghz/scenes/subghz_scene_rpc.c
@@ -22,20 +22,60 @@ bool subghz_scene_rpc_on_event(void* context, SceneManagerEvent event) {
     if(event.type == SceneManagerEventTypeCustom) {
         consumed = true;
         if(event.event == SubGhzCustomEventSceneExit) {
+            if(subghz->txrx->txrx_state == SubGhzTxRxStateTx) {
+                subghz_tx_stop(subghz);
+                subghz_sleep(subghz);
+            }
             view_dispatcher_stop(subghz->view_dispatcher);
+            rpc_system_app_confirm(subghz->rpc_ctx, RpcAppEventAppExit, true);
+        } else if(event.event == SubGhzCustomEventSceneRpcSessionClose) {
+            rpc_system_app_set_callback(subghz->rpc_ctx, NULL, NULL);
+            subghz->rpc_ctx = NULL;
+            subghz_blink_stop(subghz);
+            if(subghz->txrx->txrx_state == SubGhzTxRxStateTx) {
+                subghz_tx_stop(subghz);
+                subghz_sleep(subghz);
+            }
+            view_dispatcher_send_custom_event(subghz->view_dispatcher, SubGhzCustomEventSceneExit);
+        } else if(event.event == SubGhzCustomEventSceneRpcButtonPress) {
+            bool result = false;
+            if(subghz->txrx->txrx_state == SubGhzTxRxStateSleep) {
+                subghz_blink_start(subghz);
+                result = subghz_tx_start(subghz, subghz->txrx->fff_data);
+                result = true;
+            }
+            rpc_system_app_confirm(subghz->rpc_ctx, RpcAppEventButtonPress, result);
+        } else if(event.event == SubGhzCustomEventSceneRpcButtonRelease) {
+            bool result = false;
+            if(subghz->txrx->txrx_state == SubGhzTxRxStateTx) {
+                subghz_blink_stop(subghz);
+                subghz_tx_stop(subghz);
+                subghz_sleep(subghz);
+                result = true;
+            }
+            rpc_system_app_confirm(subghz->rpc_ctx, RpcAppEventButtonRelease, result);
         } else if(event.event == SubGhzCustomEventSceneRpcLoad) {
-            string_t file_name;
-            string_init(file_name);
-            path_extract_filename(subghz->file_path, file_name, true);
+            bool result = false;
+            const char* arg = rpc_system_app_get_data(subghz->rpc_ctx);
+            if(arg) {
+                if(subghz_key_load(subghz, arg, false)) {
+                    string_set_str(subghz->file_path, arg);
+                    result = true;
+                    string_t file_name;
+                    string_init(file_name);
+                    path_extract_filename(subghz->file_path, file_name, true);
 
-            snprintf(
-                subghz->file_name_tmp,
-                SUBGHZ_MAX_LEN_NAME,
-                "loaded\n%s",
-                string_get_cstr(file_name));
-            popup_set_text(popup, subghz->file_name_tmp, 82, 32, AlignCenter, AlignTop);
+                    snprintf(
+                        subghz->file_name_tmp,
+                        SUBGHZ_MAX_LEN_NAME,
+                        "loaded\n%s",
+                        string_get_cstr(file_name));
+                    popup_set_text(popup, subghz->file_name_tmp, 82, 32, AlignCenter, AlignTop);
 
-            string_clear(file_name);
+                    string_clear(file_name);
+                }
+            }
+            rpc_system_app_confirm(subghz->rpc_ctx, RpcAppEventLoadFile, result);
         }
     }
     return consumed;
diff --git a/applications/subghz/subghz.c b/applications/subghz/subghz.c
index a970e10c..4631d7a3 100644
--- a/applications/subghz/subghz.c
+++ b/applications/subghz/subghz.c
@@ -35,57 +35,38 @@ void subghz_tick_event_callback(void* context) {
     scene_manager_handle_tick_event(subghz->scene_manager);
 }
 
-static bool subghz_rpc_command_callback(RpcAppSystemEvent event, const char* arg, void* context) {
+static void subghz_rpc_command_callback(RpcAppSystemEvent event, void* context) {
     furi_assert(context);
     SubGhz* subghz = context;
 
-    if(!subghz->rpc_ctx) {
-        return false;
-    }
-
-    bool result = false;
+    furi_assert(subghz->rpc_ctx);
 
     if(event == RpcAppEventSessionClose) {
-        rpc_system_app_set_callback(subghz->rpc_ctx, NULL, NULL);
-        subghz->rpc_ctx = NULL;
-        notification_message(subghz->notifications, &sequence_blink_stop);
-        view_dispatcher_send_custom_event(subghz->view_dispatcher, SubGhzCustomEventSceneExit);
-        if(subghz->txrx->txrx_state == SubGhzTxRxStateTx) {
-            subghz_tx_stop(subghz);
-            subghz_sleep(subghz);
-        }
-        result = true;
+        view_dispatcher_send_custom_event(
+            subghz->view_dispatcher, SubGhzCustomEventSceneRpcSessionClose);
     } else if(event == RpcAppEventAppExit) {
         view_dispatcher_send_custom_event(subghz->view_dispatcher, SubGhzCustomEventSceneExit);
-        if(subghz->txrx->txrx_state == SubGhzTxRxStateTx) {
-            subghz_tx_stop(subghz);
-            subghz_sleep(subghz);
-        }
-        result = true;
     } else if(event == RpcAppEventLoadFile) {
-        if(arg) {
-            if(subghz_key_load(subghz, arg, false)) {
-                string_set_str(subghz->file_path, arg);
-                view_dispatcher_send_custom_event(
-                    subghz->view_dispatcher, SubGhzCustomEventSceneRpcLoad);
-                result = true;
-            }
-        }
+        view_dispatcher_send_custom_event(subghz->view_dispatcher, SubGhzCustomEventSceneRpcLoad);
     } else if(event == RpcAppEventButtonPress) {
-        if(subghz->txrx->txrx_state == SubGhzTxRxStateSleep) {
-            notification_message(subghz->notifications, &sequence_blink_start_magenta);
-            result = subghz_tx_start(subghz, subghz->txrx->fff_data);
-        }
+        view_dispatcher_send_custom_event(
+            subghz->view_dispatcher, SubGhzCustomEventSceneRpcButtonPress);
     } else if(event == RpcAppEventButtonRelease) {
-        if(subghz->txrx->txrx_state == SubGhzTxRxStateTx) {
-            notification_message(subghz->notifications, &sequence_blink_stop);
-            subghz_tx_stop(subghz);
-            subghz_sleep(subghz);
-            result = true;
-        }
+        view_dispatcher_send_custom_event(
+            subghz->view_dispatcher, SubGhzCustomEventSceneRpcButtonRelease);
+    } else {
+        rpc_system_app_confirm(subghz->rpc_ctx, event, false);
     }
+}
 
-    return result;
+void subghz_blink_start(SubGhz* instance) {
+    furi_assert(instance);
+    notification_message(instance->notifications, &sequence_blink_start_magenta);
+}
+
+void subghz_blink_stop(SubGhz* instance) {
+    furi_assert(instance);
+    notification_message(instance->notifications, &sequence_blink_stop);
 }
 
 SubGhz* subghz_alloc() {
@@ -237,7 +218,7 @@ void subghz_free(SubGhz* subghz) {
     if(subghz->rpc_ctx) {
         rpc_system_app_set_callback(subghz->rpc_ctx, NULL, NULL);
         rpc_system_app_send_exited(subghz->rpc_ctx);
-        notification_message(subghz->notifications, &sequence_blink_stop);
+        subghz_blink_stop(subghz);
         subghz->rpc_ctx = NULL;
     }
 
diff --git a/applications/subghz/subghz_i.h b/applications/subghz/subghz_i.h
index 01fbe57b..99a0f8a2 100644
--- a/applications/subghz/subghz_i.h
+++ b/applications/subghz/subghz_i.h
@@ -108,6 +108,10 @@ void subghz_begin(SubGhz* subghz, uint8_t* preset_data);
 uint32_t subghz_rx(SubGhz* subghz, uint32_t frequency);
 void subghz_rx_end(SubGhz* subghz);
 void subghz_sleep(SubGhz* subghz);
+
+void subghz_blink_start(SubGhz* instance);
+void subghz_blink_stop(SubGhz* instance);
+
 bool subghz_tx_start(SubGhz* subghz, FlipperFormat* flipper_format);
 void subghz_tx_stop(SubGhz* subghz);
 void subghz_dialog_message_show_only_rx(SubGhz* subghz);