diff --git a/ContextSaver.py b/ContextSaver.py
new file mode 100644
index 0000000000000000000000000000000000000000..24b3e497f5569675c66433a75abc628b31e0c4ed
--- /dev/null
+++ b/ContextSaver.py
@@ -0,0 +1,197 @@
+#!/usr/Local/pyroot/PyTangoRoot/bin/python
+"""
+Python module for scanning and saving configuration of devices.
+
+Includes a Command Line Interface.
+Can be imported as is to use function in user script.
+"""
+import PyTango as tango
+import logging
+import argparse
+import json
+
+__version__ = "1.0.0"
+
+##---------------------------------------------------------------------------##
+def get_wattr(proxy):
+    """
+    Get all writable attributes from a device and save their values in a python dict.
+
+    Parameters
+    ----------
+    proxy : PyTango.DeviceProxy
+    Proxy to the device.
+
+    Returns
+    -------
+    config : dict
+    Dictionnary, keys are attribute names and value their present values.
+    """
+    logger.debug("Scanning write attribute of device %s"%proxy.name())
+    config = dict()
+
+    # Scan all attributes
+    for attr in proxy.get_attribute_list():
+        if proxy.get_attribute_config(attr).writable in [
+                tango.AttrWriteType.WRITE,
+                tango.AttrWriteType.READ_WRITE,
+                tango.AttrWriteType.READ_WITH_WRITE]:
+            config[attr]=proxy[attr].value
+
+            logger.debug("Detect writtable attribute %s = %s"%(
+                attr,
+                proxy[attr].value))
+
+    return config
+
+
+##---------------------------------------------------------------------------##
+def get_properties(proxy):
+    """
+    Get all properties from a device and save them in a python dict.
+
+    Parameters
+    ----------
+    proxy : PyTango.DeviceProxy
+    Proxy to the device.
+
+    Returns
+    -------
+    config : dict
+    Dictionnary, keys are attribute names and value their present values.
+    """
+    logger.debug("Scanning properties of device %s"%proxy.name())
+
+    pl = proxy.get_property_list('*')
+
+    _props = proxy.get_property(pl)
+
+    props=dict()
+
+    # Here we simply convert tango arrays to python arrays.
+    # For properties, each prop is an array, one element in
+    # the array is a line for the property.
+    # Maybe we need to convert in one single string.
+    for k in _props.keys():
+        if k[:2] !="__":
+            # Change type
+            props[k] = list(_props[k])
+            logger.debug("Detect property %s = %s"%(
+                k, props[k]))
+
+
+    return props
+
+
+##########################################################################
+""" Command Line Interface """
+if __name__ == "__main__":
+
+    # Name the logger after the filename
+    logger = logging.getLogger("ContextSaver")
+
+    #######################################################
+    # Install argument parser
+    import argparse
+
+    parser = argparse.ArgumentParser(description="Copy attributes and properties to a JSON structure.\n"+
+            "Version %s"%__version__)
+
+    parser.add_argument("--fileout", type=str,
+            help="Save the JSON structure to the specified file. Implicit set no output to stdout."),
+
+    parser.add_argument('--log', type=str, default="INFO",
+            help="Log level. Default: %(default)s.")
+
+    parser.add_argument('-v', action="store_true",
+            help="Print in stdout the context. Default is on if no fileout option specified.")
+
+    parser.add_argument('--filemode', action="store_true",
+            help="Set devices to filemode."+
+            " Instead of specifying devices, put a path to a file containing a list of devices."+
+            " The file contains one device path per line.")
+
+    parser.add_argument('devices', type=str, nargs='+',
+                        help="List of devices to inspect. Full tango path.")
+
+    args = parser.parse_args()
+
+
+    #######################################################
+    # Configure logger
+
+    # Add a stream handler
+    s_handler = logging.StreamHandler()
+    s_handler.setFormatter(logging.Formatter("%(levelname)s\t[%(funcName)s] \t%(message)s"))
+
+    # Set level according to command line attribute
+    s_handler.setLevel(level=getattr(logging, args.log.upper()))
+    logger.setLevel(level=getattr(logging, args.log.upper()))
+    logger.addHandler(s_handler)
+
+    logger.debug("Parsed arguments: %s"%args)
+
+    logger.info("Context Saver %s"%__version__)
+
+    #######################################################
+    # Filemode or not
+    if args.filemode:
+        logger.info("Filemode, openning file %s"%args.devices[0])
+        # Read the file. Each line is an device
+        with open(args.devices[0], "r") as fp:
+            devices = fp.readlines()
+
+        logger.debug("Read lines : %s"%devices)
+
+        # Clean end of line
+        for i_a in range(len(devices)):
+            devices[i_a] = devices[i_a].rstrip()
+
+    else:
+        devices = args.devices
+
+    #######################################################
+    # Prepare array for result
+    results = []
+
+    #######################################################
+    # Scan all devices
+
+    for dev in devices:
+        logger.info("Scanning device %s..."%dev)
+
+        # Declare proxy
+        prx = tango.DeviceProxy(dev)
+
+        # Retrieve write attributes
+        wattr = get_wattr(prx)
+
+        # Retrieve properties
+        props = get_properties(prx)
+
+        # Build json dict
+        jdict = {
+                "tangopath":dev,
+                "wattributes":wattr,
+                "properties":props,
+                }
+
+        # Add to results
+        results.append(jdict)
+
+    logger.info("Done")
+
+    if args.fileout is None:
+        print(json.dumps(results, indent=4))
+    else:
+        with open(args.fileout, "w") as fp:
+            json.dump(results, fp, indent=4)
+
+        # Additionnal dump to stdout
+        if args.v:
+            print(json.dumps(results, indent=4))
+
+
+else:
+    # Name the logger after the module name
+    logger = logging.getLogger(__name__)