diff --git a/src/commands/getMemInfo.js b/src/commands/getMemInfo.js
new file mode 100644
index 00000000..8b175181
--- /dev/null
+++ b/src/commands/getMemInfo.js
@@ -0,0 +1,19 @@
+// @flow
+
+import { createCommand, Command } from 'helpers/ipc'
+import { fromPromise } from 'rxjs/observable/fromPromise'
+
+import { withDevice } from 'helpers/deviceAccess'
+import getMemInfo from 'helpers/devices/getMemInfo'
+
+type Input = {
+  devicePath: string,
+}
+
+type Result = *
+
+const cmd: Command<Input, Result> = createCommand('devices', 'getMemInfo', ({ devicePath }) =>
+  fromPromise(withDevice(devicePath)(transport => getMemInfo(transport))),
+)
+
+export default cmd
diff --git a/src/commands/installApp.js b/src/commands/installApp.js
index d9f6d530..792a5661 100644
--- a/src/commands/installApp.js
+++ b/src/commands/installApp.js
@@ -2,8 +2,8 @@
 
 import { createCommand, Command } from 'helpers/ipc'
 import { fromPromise } from 'rxjs/observable/fromPromise'
-import { withDevice } from 'helpers/deviceAccess'
 
+import { withDevice } from 'helpers/deviceAccess'
 import installApp from 'helpers/apps/installApp'
 
 import type { LedgerScriptParams } from 'helpers/common'
diff --git a/src/commands/installFinalFirmware.js b/src/commands/installFinalFirmware.js
new file mode 100644
index 00000000..775dd743
--- /dev/null
+++ b/src/commands/installFinalFirmware.js
@@ -0,0 +1,28 @@
+// @flow
+
+import { createCommand, Command } from 'helpers/ipc'
+import { fromPromise } from 'rxjs/observable/fromPromise'
+import { withDevice } from 'helpers/deviceAccess'
+
+import installFinalFirmware from 'helpers/firmware/installFinalFirmware'
+
+type Input = {
+  devicePath: string,
+  firmware: Object,
+}
+
+type Result = {
+  targetId: number | string,
+  version: string,
+  final: boolean,
+  mcu: boolean,
+}
+
+const cmd: Command<Input, Result> = createCommand(
+  'devices',
+  'installFinalFirmware',
+  ({ devicePath, firmware }) =>
+    fromPromise(withDevice(devicePath)(transport => installFinalFirmware(transport, firmware))),
+)
+
+export default cmd
diff --git a/src/commands/installMcu.js b/src/commands/installMcu.js
new file mode 100644
index 00000000..b1fa57ed
--- /dev/null
+++ b/src/commands/installMcu.js
@@ -0,0 +1,28 @@
+// @flow
+
+import { createCommand, Command } from 'helpers/ipc'
+import { fromPromise } from 'rxjs/observable/fromPromise'
+
+// import { withDevice } from 'helpers/deviceAccess'
+import installMcu from 'helpers/firmware/installMcu'
+
+// type Input = {
+//   devicePath: string,
+//   firmware: Object,
+// }
+
+// type Result = {
+//   targetId: number | string,
+//   version: string,
+//   final: boolean,
+//   mcu: boolean,
+// }
+
+type Input = *
+type Result = *
+
+const cmd: Command<Input, Result> = createCommand('devices', 'installMcu', () =>
+  fromPromise(installMcu()),
+)
+
+export default cmd
diff --git a/src/commands/installOsuFirmware.js b/src/commands/installOsuFirmware.js
new file mode 100644
index 00000000..f5110b13
--- /dev/null
+++ b/src/commands/installOsuFirmware.js
@@ -0,0 +1,28 @@
+// @flow
+
+import { createCommand, Command } from 'helpers/ipc'
+import { fromPromise } from 'rxjs/observable/fromPromise'
+import { withDevice } from 'helpers/deviceAccess'
+
+import installOsuFirmware from 'helpers/firmware/installOsuFirmware'
+
+type Input = {
+  devicePath: string,
+  firmware: Object,
+}
+
+type Result = {
+  targetId: number | string,
+  version: string,
+  final: boolean,
+  mcu: boolean,
+}
+
+const cmd: Command<Input, Result> = createCommand(
+  'devices',
+  'installOsuFirmware',
+  ({ devicePath, firmware }) =>
+    fromPromise(withDevice(devicePath)(transport => installOsuFirmware(transport, firmware))),
+)
+
+export default cmd
diff --git a/src/commands/listenDevices.js b/src/commands/listenDevices.js
new file mode 100644
index 00000000..d3ea3aeb
--- /dev/null
+++ b/src/commands/listenDevices.js
@@ -0,0 +1,9 @@
+// @flow
+
+import { createCommand } from 'helpers/ipc'
+import { Observable } from 'rxjs'
+import CommNodeHid from '@ledgerhq/hw-transport-node-hid'
+
+const cmd = createCommand('devices', 'listenDevices', () => Observable.create(CommNodeHid.listen))
+
+export default cmd
diff --git a/src/commands/uninstallApp.js b/src/commands/uninstallApp.js
new file mode 100644
index 00000000..a07a2e8f
--- /dev/null
+++ b/src/commands/uninstallApp.js
@@ -0,0 +1,25 @@
+// @flow
+
+import { createCommand, Command } from 'helpers/ipc'
+import { fromPromise } from 'rxjs/observable/fromPromise'
+import { withDevice } from 'helpers/deviceAccess'
+
+import uninstallApp from 'helpers/apps/uninstallApp'
+
+import type { LedgerScriptParams } from 'helpers/common'
+
+type Input = {
+  appParams: LedgerScriptParams,
+  devicePath: string,
+}
+
+type Result = *
+
+const cmd: Command<Input, Result> = createCommand(
+  'devices',
+  'uninstallApp',
+  ({ devicePath, ...rest }) =>
+    fromPromise(withDevice(devicePath)(transport => uninstallApp(transport, rest))),
+)
+
+export default cmd
diff --git a/src/components/ManagerPage/AppsList.js b/src/components/ManagerPage/AppsList.js
index 19581ff0..66d8dd88 100644
--- a/src/components/ManagerPage/AppsList.js
+++ b/src/components/ManagerPage/AppsList.js
@@ -107,8 +107,8 @@ class AppsList extends PureComponent<Props, State> {
             name={c.name}
             version={`Version ${c.version}`}
             icon={ICONS_FALLBACK[c.icon] || c.icon}
-            onInstall={() => {}}
-            onUninstall={() => {}}
+            onInstall={this.handleInstallApp(c)}
+            onUninstall={this.handleUninstallApp()}
           />
         ))}
         <Modal
diff --git a/src/components/ManagerPage/index.js b/src/components/ManagerPage/index.js
index 68b45ba5..88d5b9b7 100644
--- a/src/components/ManagerPage/index.js
+++ b/src/components/ManagerPage/index.js
@@ -5,57 +5,22 @@ import { translate } from 'react-i18next'
 
 import type { T } from 'types/common'
 
-// import Pills from 'components/base/Pills'
-
 import AppsList from './AppsList'
 // import DeviceInfos from './DeviceInfos'
-// import FirmwareUpdate from './FirmwareUpdate'
+import FirmwareUpdate from './FirmwareUpdate'
 import EnsureDevice from './EnsureDevice'
 import EnsureDashboard from './EnsureDashboard'
 import EnsureGenuine from './EnsureGenuine'
 
-const TABS = [{ key: 'apps', value: 'apps' }, { key: 'device', value: 'device' }]
-
 type Props = {
   t: T,
 }
 
-type State = {
-  // currentTab: 'apps' | 'device',
-}
+type State = {}
 
 class ManagerPage extends Component<Props, State> {
-  // state = {
-  //   currentTab: 'apps',
-  // }
-
-  // componentWillReceiveProps(nextProps) {
-  //   const { device } = this.props
-  //   const { currentTab } = this.state
-  //   if (device && !nextProps.device && currentTab === 'device') {
-  //     this.setState({ currentTab: 'apps' })
-  //   }
-  // }
-
-  // handleTabChange = t => this.setState({ currentTab: t.value })
-
-  createTabs = (device, nbDevices) => {
-    const { t } = this.props
-    return TABS.map(i => {
-      let label = t(`manager:tabs.${i.key}`)
-      if (i.key === 'device') {
-        if (!device) {
-          return null
-        }
-        label += ` (${nbDevices})`
-      }
-      return { ...i, label }
-    }).filter(Boolean)
-  }
-
   render() {
     const { t } = this.props
-    // const { currentTab } = this.state
 
     return (
       <Fragment>
@@ -64,26 +29,20 @@ class ManagerPage extends Component<Props, State> {
             <EnsureDashboard device={device}>
               {deviceInfo => (
                 <Fragment>
-                  {/* <Pills
-                    items={this.createTabs(device, nbDevices)}
-                    activeKey={currentTab}
-                    onChange={this.handleTabChange}
-                    mb={6}
-                  /> */}
                   {deviceInfo.mcu && <span>bootloader mode</span>}
                   {deviceInfo.final && <span>osu mode</span>}
 
                   {!deviceInfo.mcu &&
                     !deviceInfo.final && (
                       <EnsureGenuine device={device} t={t}>
-                        {/* <FirmwareUpdate
+                        <FirmwareUpdate
                           infos={{
                             targetId: deviceInfo.targetId,
                             version: deviceInfo.version,
                           }}
                           device={device}
                           t={t}
-                        /> */}
+                        />
                         <AppsList device={device} />
                       </EnsureGenuine>
                     )}
diff --git a/src/helpers/apps/uninstallApp.js b/src/helpers/apps/uninstallApp.js
index 5fa45564..99a4175a 100644
--- a/src/helpers/apps/uninstallApp.js
+++ b/src/helpers/apps/uninstallApp.js
@@ -1,12 +1,16 @@
 // @flow
 
-// import type { IPCSend } from 'types/electron'
+import type Transport from '@ledgerhq/hw-transport'
 
-// import { createTransportHandler, uninstallApp } from 'helpers/common'
+import { createSocketDialog } from 'helpers/common'
+import type { LedgerScriptParams } from 'helpers/common'
 
-// export default (send: IPCSend, data: any) =>
-//   createTransportHandler(send, {
-//     action: uninstallApp,
-//     successResponse: 'manager.appUninstalled',
-//     errorResponse: 'manager.appUninstallError',
-//   })(data)
+/**
+ * Install an app on the device
+ */
+export default async function uninstallApp(
+  transport: Transport<*>,
+  { appParams }: { appParams: LedgerScriptParams },
+): Promise<void> {
+  return createSocketDialog(transport, '/update/install', appParams)
+}
diff --git a/src/helpers/devices/getMemInfo.js b/src/helpers/devices/getMemInfo.js
new file mode 100644
index 00000000..5e5ad62e
--- /dev/null
+++ b/src/helpers/devices/getMemInfo.js
@@ -0,0 +1,11 @@
+// @flow
+
+import type Transport from '@ledgerhq/hw-transport'
+
+import { getFirmwareInfo, createSocketDialog } from 'helpers/common'
+
+export default async function getMemInfos(transport: Transport<*>): Promise<Object> {
+  const { targetId } = await getFirmwareInfo(transport)
+  // Dont ask me about this `perso_11`: I don't know. But we need it.
+  return createSocketDialog(transport, '/get-mem-infos', { targetId, perso: 'perso_11' })
+}
diff --git a/src/helpers/firmware/installFinalFirmware.js b/src/helpers/firmware/installFinalFirmware.js
index 6e77ecdd..af3410ac 100644
--- a/src/helpers/firmware/installFinalFirmware.js
+++ b/src/helpers/firmware/installFinalFirmware.js
@@ -1,24 +1,26 @@
 // @flow
 
-import CommNodeHid from '@ledgerhq/hw-transport-node-hid'
+import type Transport from '@ledgerhq/hw-transport'
 
-import type { IPCSend } from 'types/electron'
 import { createSocketDialog, buildParamsFromFirmware } from 'helpers/common'
 
-type DataType = {
-  devicePath: string,
+type Input = {
   firmware: Object,
 }
 
-const buildFinalParams = buildParamsFromFirmware('final')
+type Result = *
 
-export default async (send: IPCSend, data: DataType) => {
+const buildOsuParams = buildParamsFromFirmware('final')
+
+export default async (transport: Transport<*>, data: Input): Result => {
   try {
-    const transport = await CommNodeHid.open(data.devicePath)
-    const finalData = buildFinalParams(data.firmware)
-    await createSocketDialog(transport, '/update/install', finalData)
-    send('device.finalFirmwareInstallSuccess', { success: true })
+    const osuData = buildOsuParams(data.firmware)
+    await createSocketDialog(transport, '/update/install', osuData)
+    return { success: true }
   } catch (err) {
-    send('device.finalFirmwareInstallError', { success: false })
+    const error = Error(err.message)
+    error.stack = err.stack
+    const result = { success: false, error }
+    throw result
   }
 }
diff --git a/src/helpers/firmware/installMcu.js b/src/helpers/firmware/installMcu.js
index 0f8b7d99..e44f4d47 100644
--- a/src/helpers/firmware/installMcu.js
+++ b/src/helpers/firmware/installMcu.js
@@ -1 +1,8 @@
-// flow
+// @flow
+
+type Result = Promise<boolean>
+
+// TODO: IMPLEMENTATION FOR FLASHING FIRMWARE
+// GETTING APDUS FROM SERVER
+// SEND THE APDUS TO DEVICE
+export default async (): Result => new Promise(resolve => resolve(true))
diff --git a/src/internals/devices/index.js b/src/internals/devices/index.js
index 6679260e..7500c00a 100644
--- a/src/internals/devices/index.js
+++ b/src/internals/devices/index.js
@@ -10,10 +10,11 @@ import getFirmwareInfo from 'commands/getFirmwareInfo'
 import getIsGenuine from 'commands/getIsGenuine'
 import getLatestFirmwareForDevice from 'commands/getLatestFirmwareForDevice'
 import installApp from 'commands/installApp'
-import listen from './listen'
-
-// TODO port these to commands
-export { listen }
+import listenDevices from 'commands/listenDevices'
+import uninstallApp from 'commands/uninstallApp'
+import installOsuFirmware from 'commands/installOsuFirmware'
+import installFinalFirmware from 'commands/installFinalFirmware'
+import installMcu from 'commands/installMcu'
 
 export const commands: Array<Command<any, any>> = [
   getAddress,
@@ -25,4 +26,9 @@ export const commands: Array<Command<any, any>> = [
   installApp,
   libcoreScanAccounts,
   libcoreSignAndBroadcast,
+  listenDevices,
+  uninstallApp,
+  installOsuFirmware,
+  installFinalFirmware,
+  installMcu,
 ]
diff --git a/src/internals/devices/listen.js b/src/internals/devices/listen.js
deleted file mode 100644
index 5c5c68e4..00000000
--- a/src/internals/devices/listen.js
+++ /dev/null
@@ -1,24 +0,0 @@
-// @flow
-
-import CommNodeHid from '@ledgerhq/hw-transport-node-hid'
-import noop from 'lodash/noop'
-
-import type { IPCSend } from 'types/electron'
-
-export default (send: IPCSend) => {
-  CommNodeHid.listen({
-    error: noop,
-    complete: noop,
-    next: async e => {
-      if (!e.device) {
-        return
-      }
-      if (e.type === 'add') {
-        send('device.add', e.device, { kill: false })
-      }
-      if (e.type === 'remove') {
-        send('device.remove', e.device, { kill: false })
-      }
-    },
-  })
-}
diff --git a/src/internals/manager/constants.js b/src/internals/manager/constants.js
deleted file mode 100644
index 3ca86b53..00000000
--- a/src/internals/manager/constants.js
+++ /dev/null
@@ -1,13 +0,0 @@
-// Socket endpoint
-
-export const BASE_SOCKET_URL = 'ws://api.ledgerwallet.com'
-// If you want to test locally with https://github.com/LedgerHQ/ledger-update-python-api
-// export const BASE_SOCKET_URL = 'ws://localhost:3001/update'
-
-// List of APDUS
-export const APDUS = {
-  GET_FIRMWARE: [0xe0, 0x01, 0x00, 0x00],
-  // we dont have common call that works inside app & dashboard
-  // TODO: this should disappear.
-  GET_FIRMWARE_FALLBACK: [0xe0, 0xc4, 0x00, 0x00],
-}
diff --git a/src/internals/manager/getMemInfos.js b/src/internals/manager/getMemInfos.js
deleted file mode 100644
index 34845888..00000000
--- a/src/internals/manager/getMemInfos.js
+++ /dev/null
@@ -1,12 +0,0 @@
-// @flow
-
-import type { IPCSend } from 'types/electron'
-
-import { createTransportHandler, getMemInfos } from './helpers'
-
-export default (send: IPCSend, data: any) =>
-  createTransportHandler(send, {
-    action: getMemInfos,
-    successResponse: 'manager.getMemInfosSuccess',
-    errorResponse: 'manager.getMemInfosError',
-  })(data)
diff --git a/src/internals/manager/helpers.js b/src/internals/manager/helpers.js
deleted file mode 100644
index 2a41210d..00000000
--- a/src/internals/manager/helpers.js
+++ /dev/null
@@ -1,237 +0,0 @@
-// @flow
-
-import { withDevice } from 'helpers/deviceAccess'
-import chalk from 'chalk'
-import Websocket from 'ws'
-import qs from 'qs'
-import type Transport from '@ledgerhq/hw-transport'
-
-import type { IPCSend } from 'types/electron'
-import { BASE_SOCKET_URL, APDUS } from './constants'
-
-// TODO: REMOVE FILE WHEN REFACTO IS OVER
-
-type WebsocketType = {
-  send: (string, any) => void,
-  on: (string, Function) => void,
-}
-
-type Message = {
-  nonce: number,
-  query?: string,
-  response?: string,
-  data: any,
-}
-
-type LedgerScriptParams = {
-  firmware?: string,
-  firmwareKey?: string,
-  delete?: string,
-  deleteKey?: string,
-}
-
-/**
- * Generate handler which create transport with given
- * `devicePath` then call action with it
- */
-export function createTransportHandler(
-  send: IPCSend,
-  {
-    action,
-    successResponse,
-    errorResponse,
-  }: {
-    action: (Transport<*>, ...any) => Promise<any>,
-    successResponse: string,
-    errorResponse: string,
-  },
-) {
-  console.log('DEPRECATED: createTransportHandler use withDevice and commands/*')
-  return async function transportHandler({
-    devicePath,
-    ...params
-  }: {
-    devicePath: string,
-  }): Promise<void> {
-    try {
-      const data = await withDevice(devicePath)(transport => action(transport, params))
-      send(successResponse, data)
-    } catch (err) {
-      if (!err) {
-        send(errorResponse, { message: 'Unknown error...' })
-      }
-      send(errorResponse, { message: err.message, stack: err.stack })
-    }
-  }
-}
-
-export async function getMemInfos(transport: Transport<*>): Promise<Object> {
-  const { targetId } = await getFirmwareInfo(transport)
-  // Dont ask me about this `perso_11`: I don't know. But we need it.
-  return createSocketDialog(transport, '/get-mem-infos', { targetId, perso: 'perso_11' })
-}
-
-/**
- * Send data through ws
- */
-function socketSend(ws: WebsocketType, msg: Message) {
-  logWS('SEND', msg)
-  const strMsg = JSON.stringify(msg)
-  ws.send(strMsg)
-}
-
-/**
- * Exchange data on transport
- */
-export async function exchange(
-  ws: WebsocketType,
-  transport: Transport<*>,
-  msg: Message,
-): Promise<void> {
-  const { data, nonce } = msg
-  const r: Buffer = await transport.exchange(Buffer.from(data, 'hex'))
-  const status = r.slice(r.length - 2)
-  const buffer = r.slice(0, r.length - 2)
-  const strStatus = status.toString('hex')
-  socketSend(ws, {
-    nonce,
-    response: strStatus === '9000' ? 'success' : 'error',
-    data: buffer.toString('hex'),
-  })
-}
-
-/**
- * Bulk update on transport
- */
-export async function bulk(ws: WebsocketType, transport: Transport<*>, msg: Message) {
-  const { data, nonce } = msg
-
-  // Execute all apdus and collect last status
-  let lastStatus = null
-  for (const apdu of data) {
-    const r: Buffer = await transport.exchange(Buffer.from(apdu, 'hex'))
-    lastStatus = r.slice(r.length - 2)
-  }
-  if (!lastStatus) {
-    throw new Error('No status collected from bulk')
-  }
-
-  const strStatus = lastStatus.toString('hex')
-  socketSend(ws, {
-    nonce,
-    response: strStatus === '9000' ? 'success' : 'error',
-    data: strStatus === '9000' ? '' : strStatus,
-  })
-}
-
-/**
- * Open socket connection with firmware api, and init a dialog
- * with the device
- */
-export async function createSocketDialog(
-  transport: Transport<*>,
-  endpoint: string,
-  params: LedgerScriptParams,
-) {
-  return new Promise(async (resolve, reject) => {
-    try {
-      let lastData
-      const url = `${BASE_SOCKET_URL}${endpoint}?${qs.stringify(params)}`
-
-      log('WS CONNECTING', url)
-      const ws: WebsocketType = new Websocket(url)
-
-      ws.on('open', () => log('WS CONNECTED'))
-
-      ws.on('close', () => {
-        log('WS CLOSED')
-        resolve(lastData)
-      })
-
-      ws.on('message', async rawMsg => {
-        const handlers = {
-          exchange: msg => exchange(ws, transport, msg),
-          bulk: msg => bulk(ws, transport, msg),
-          success: msg => {
-            if (msg.data) {
-              lastData = msg.data
-            }
-          },
-          error: msg => {
-            log('WS ERROR', ':(')
-            throw new Error(msg.data)
-          },
-        }
-        try {
-          const msg = JSON.parse(rawMsg)
-          if (!(msg.query in handlers)) {
-            throw new Error(`Cannot handle msg of type ${msg.query}`)
-          }
-          logWS('RECEIVE', msg)
-          await handlers[msg.query](msg)
-        } catch (err) {
-          log('ERROR', err.toString())
-          reject(err)
-        }
-      })
-    } catch (err) {
-      reject(err)
-    }
-  })
-}
-
-/**
- * Retrieve targetId and firmware version from device
- */
-export async function getFirmwareInfo(transport: Transport<*>) {
-  try {
-    const res = await transport.send(...APDUS.GET_FIRMWARE)
-    const byteArray = [...res]
-    const data = byteArray.slice(0, byteArray.length - 2)
-    const targetIdStr = Buffer.from(data.slice(0, 4))
-    const targetId = targetIdStr.readUIntBE(0, 4)
-    const versionLength = data[4]
-    const version = Buffer.from(data.slice(5, 5 + versionLength)).toString()
-    return { targetId, version }
-  } catch (err) {
-    const error = new Error(err.message)
-    error.stack = err.stack
-    throw error
-  }
-}
-
-/**
- * Debug helper
- */
-export function log(namespace: string, str: string = '', color?: string) {
-  namespace = namespace.padEnd(15)
-  // $FlowFixMe
-  const coloredNamespace = color ? chalk[color](namespace) : namespace
-  if (__DEV__) {
-    console.log(`${chalk.bold(`> ${coloredNamespace}`)} ${str}`) // eslint-disable-line no-console
-  }
-}
-
-/**
- * Log a socket send/receive
- */
-export function logWS(type: string, msg: Message) {
-  const arrow = type === 'SEND' ? '↑' : '↓'
-  const namespace = `${arrow} WS ${type}`
-  const color = type === 'SEND' ? 'blue' : 'red'
-  if (msg.nonce) {
-    let d = ''
-    if (msg.query === 'exchange') {
-      d = msg.data.length > 100 ? `${msg.data.substr(0, 97)}...` : msg.data
-    } else if (msg.query === 'bulk') {
-      d = `[bulk x ${msg.data.length}]`
-    }
-    log(
-      namespace,
-      `${String(msg.nonce).padEnd(2)} ${(msg.response || msg.query || '').padEnd(10)} ${d}`,
-      color,
-    )
-  } else {
-    log(namespace, JSON.stringify(msg), color)
-  }
-}
diff --git a/src/internals/manager/index.js b/src/internals/manager/index.js
index 3b2c0349..7f7a94af 100644
--- a/src/internals/manager/index.js
+++ b/src/internals/manager/index.js
@@ -2,6 +2,7 @@
 import type { Command } from 'helpers/ipc'
 
 import listApps from 'commands/listApps'
+import getMemInfo from 'commands/getMemInfo'
 
 /**
  *                                  Manager
@@ -19,6 +20,4 @@ import listApps from 'commands/listApps'
  *
  */
 
-export { default as getMemInfos } from './getMemInfos'
-
-export const commands: Array<Command<any, any>> = [listApps]
+export const commands: Array<Command<any, any>> = [listApps, getMemInfo]
diff --git a/src/renderer/events.js b/src/renderer/events.js
index b5341eaf..1833ea72 100644
--- a/src/renderer/events.js
+++ b/src/renderer/events.js
@@ -18,6 +18,8 @@ import { setUpdateStatus } from 'reducers/update'
 
 import { addDevice, removeDevice } from 'actions/devices'
 
+import listenDevices from 'commands/listenDevices'
+
 import i18n from 'renderer/i18n/electron'
 
 const d = {
@@ -51,16 +53,6 @@ export default ({ store }: { store: Object, locked: boolean }) => {
     application: {
       changeLanguage: lang => i18n.changeLanguage(lang),
     },
-    device: {
-      add: device => {
-        d.device('Device - add')
-        store.dispatch(addDevice(device))
-      },
-      remove: device => {
-        d.device('Device - remove')
-        store.dispatch(removeDevice(device))
-      },
-    },
     updater: {
       checking: () => store.dispatch(setUpdateStatus('checking')),
       updateAvailable: info => store.dispatch(setUpdateStatus('available', info)),
@@ -70,7 +62,6 @@ export default ({ store }: { store: Object, locked: boolean }) => {
       downloaded: () => store.dispatch(setUpdateStatus('downloaded')),
     },
   }
-
   ipcRenderer.on('msg', (event: any, payload: MsgPayload) => {
     const { type, data } = payload
     const handler = objectPath.get(handlers, type)
@@ -83,8 +74,19 @@ export default ({ store }: { store: Object, locked: boolean }) => {
   // Ensure all sub-processes are killed before creating new ones (dev mode...)
   ipcRenderer.send('clean-processes')
 
-  // Start detection when we plug/unplug devices
-  sendEvent('devices', 'listen')
+  listenDevices.send().subscribe({
+    next: ({ device, type }) => {
+      if (device) {
+        if (type === 'add') {
+          d.device('Device - add')
+          store.dispatch(addDevice(device))
+        } else if (type === 'remove') {
+          d.device('Device - remove')
+          store.dispatch(removeDevice(device))
+        }
+      }
+    },
+  })
 
   if (__PROD__) {
     // Start check of eventual updates