diff --git a/doc/man/ade-info.1 b/doc/man/ade-info.1
index ca20162ae3ab68bd827d52ad368d2d300abd25f6..d460c6528cd289df35ca6674959a43669496469a 100644
--- a/doc/man/ade-info.1
+++ b/doc/man/ade-info.1
@@ -12,6 +12,7 @@ ade-info \- Print information about an entity
 .SH SYNOPSIS
 .sp
 .nf
+\fIade info\fR --device [<user>[:<pass>]@]<hostname>[:<port>]
 \fIade info\fR --sysroot <sysroot>
 .fi
 .sp
@@ -22,6 +23,12 @@ Retrieve information about a sysroot or another ADE object\&.
 .SH OPTIONS
 .sp
 .PP
+\fI\-\-device\fR
+.RS 4
+Return image version of given device (e.g. user@apertis)\&.
+.sp
+.RE
+.PP
 \fI\-\-sysroot\fR
 .RS 4
 Return installed version and path of given sysroot (e.g. apertis-16.12-armhf)\&.
diff --git a/tools/ade b/tools/ade
index 65c54e48be9a05c89269a3e32a36a5be85e4c148..99d88161b59605588a0e59fe2740cae9e29f1367 100755
--- a/tools/ade
+++ b/tools/ade
@@ -17,6 +17,7 @@ import glob
 import logging
 import os
 import pathlib
+import paramiko
 import re
 import shutil
 import struct
@@ -26,6 +27,7 @@ import tempfile
 import urllib
 import xdg.BaseDirectory
 
+from contextlib import contextmanager, closing
 from urllib.error import URLError
 from urllib.parse import urlparse
 from urllib.request import urlopen, urlretrieve
@@ -53,6 +55,14 @@ class SysrootManagerError(Exception):
         return self.message
 
 
+class InvalidDeviceError(Exception):
+    def __init__(self, message):
+        self.message = message
+
+    def __str__(self):
+        return self.message
+
+
 class InvalidSysrootArchiveError(Exception):
     def __init__(self, message):
         self.message = message
@@ -120,6 +130,66 @@ class TargetTriplet:
         raise NotSupportedError
 
 
+class Device:
+
+    def __init__(self, host, port=22, user=None, password=None):
+        self.host = host
+        if port is None:
+            port = 22
+        self.port = port
+        self.user = user
+        if not self.user:
+            self.user = "user"
+        self.password = password
+        self.version = None
+        self._ssh = None
+
+    def from_uri(uri):
+        try:
+            r = urlparse("ssh://" + uri)
+        except Exception:
+            raise InvalidDeviceError("Invalid URI format")
+        return Device(r.hostname, r.port, r.username, r.password)
+
+    def __str__(self):
+        string = ""
+        if self.user:
+            string += user
+            if self.password:
+                string += ':' + self.password
+            string += '@'
+        string += self.host
+        if self.port != 22:
+            string += ':' + str(self.port)
+        return string
+
+    def _connect(self):
+        ssh = paramiko.SSHClient()
+        ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
+        ssh.connect(self.host, port=self.port,
+                    allow_agent=False, look_for_keys=False, gss_auth=False,
+                    username=self.user, password=self.password,
+                    key_filename=os.path.expanduser("~/.ssh/apertis.ssh"))
+        return ssh
+
+    def _exec(self, *args):
+        with closing(self._connect()) as ssh:
+            stdin, stdout, stderr = ssh.exec_command(' '.join(args))
+            return stdout.read().decode().strip()
+
+    def load_sysroot_version(self):
+        try:
+            v = self._exec('cat', '/etc/image_version')
+            self.version = SysrootVersion.from_string(v)
+        except Exception as e:
+            print(e)
+            raise InvalidDeviceError("No image_version file found")
+        a = self._exec('uname', '-m')
+        if a not in TargetTriplet.SUPPORTED:
+            raise InvalidDeviceError("Unsupported architecture")
+        self.version.arch = a
+
+
 class SysrootVersion:
 
     def __init__(self, distro, release, arch, date=None, build=None, author=None, url=None):
@@ -486,6 +556,7 @@ class Ade:
 
         self.target = None
         self.sysroot = None
+        self.device = None
 
         self.sysroot_version = None
         self.distro = None
@@ -550,8 +621,14 @@ class Ade:
             except InvalidSysrootError:
                 self.die("Invalid sysroot installed for {0}{1}{2}" \
                          .format(Colors.OKBLUE, version.get_name(), Colors.ENDC))
+        elif self.device:
+            try:
+                self.target = Device.from_uri(self.device)
+                self.target.load_sysroot_version()
+            except InvalidDeviceError as e:
+                self.die("Invalid device: {0}".format(e))
         else:
-            self.die("No target (sysroot) specified")
+            self.die("No target (sysroot or device) specified")
 
         return self.target
 
@@ -749,6 +826,11 @@ class Ade:
             if self.format == 'parseable':
                 print("SysrootVersion:{0}".format(self.target.version.get_tag()))
                 print("SysrootPath:{0}".format(self.target.path))
+        elif isinstance(target, Device):
+            self.info("* Device has image version {0}{1}{2}"
+                    .format(Colors.WARNING, self.target.version, Colors.ENDC))
+            if self.format == 'parseable':
+                print("ImageVersion:{0}".format(self.target.version.get_tag()))
 
     def info(self, message):
         if self.format == 'friendly':
@@ -780,6 +862,7 @@ if __name__ == '__main__':
     info_parser = subparsers.add_parser('info', help="Retrieve information about an object")
     group = info_parser.add_mutually_exclusive_group()
     group.add_argument('--sysroot', help="Use sysroot as target (e.g. apertis-16.12-armhf)")
+    group.add_argument('--device', help="Use device as target (e.g. user:pass@apertis)")
 
     # Sysroot parser
     sysroot_parser = subparsers.add_parser('sysroot', help='Sysroot related commands')