diff --git a/cli/omci.py b/cli/omci.py
new file mode 100644
index 0000000..146f296
--- /dev/null
+++ b/cli/omci.py
@@ -0,0 +1,356 @@
+#!/usr/bin/env python
+#
+# Copyright 2018 the original author or authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+"""
+OpenOMCI level CLI commands
+"""
+from optparse import make_option
+from cmd2 import Cmd, options
+from datetime import datetime
+from google.protobuf.empty_pb2 import Empty
+from cli.table import print_pb_list_as_table
+from voltha.protos import third_party
+from voltha.protos import voltha_pb2
+from voltha.protos.omci_mib_db_pb2 import MibDeviceData, MibClassData, \
+    MibInstanceData
+from os import linesep
+
+_ = third_party
+
+
+class OmciCli(Cmd):
+    CREATED_KEY = 'created'
+    MODIFIED_KEY = 'modified'
+    MDS_KEY = 'mib_data_sync'
+    LAST_SYNC_KEY = 'last_mib_sync'
+    VERSION_KEY = 'version'
+    DEVICE_ID_KEY = 'device_id'
+    CLASS_ID_KEY = 'class_id'
+    INSTANCE_ID_KEY = 'instance_id'
+    ATTRIBUTES_KEY = 'attributes'
+    TIME_FORMAT = '%Y%m%d-%H%M%S.%f'
+    ME_KEY = 'managed_entities'
+    MSG_TYPE_KEY = 'message_types'
+
+    MSG_TYPE_TO_NAME = {
+        4: 'Create',
+        5: 'Create Complete',
+        6: 'Delete',
+        8: 'Set',
+        9: 'Get',
+        10: 'Get Complete',
+        11: 'Get All Alarms',
+        12: 'Get All Alarms Next',
+        13: 'Mib Upload',
+        14: 'Mib Upload Next',
+        15: 'Mib Reset',
+        16: 'Alarm Notification',
+        17: 'Attribute Value Change',
+        18: 'Test',
+        19: 'Start Software Download',
+        20: 'Download Section',
+        21: 'End Software Download',
+        22: 'Activate Software',
+        23: 'Commit Software',
+        24: 'Synchronize Time',
+        25: 'Reboot',
+        26: 'Get Next',
+        27: 'Test Result',
+        28: 'Get Current Data',
+        29: 'Set Table'
+    }
+
+    def __init__(self, device_id, get_stub):
+        Cmd.__init__(self)
+        self.get_stub = get_stub
+        self.device_id = device_id
+        self.prompt = '(' + self.colorize(
+            self.colorize('omci {}'.format(device_id), 'green'),
+            'bold') + ') '
+
+    def cmdloop(self, intro=None):
+        self._cmdloop()
+
+    do_exit = Cmd.do_quit
+
+    def do_quit(self, line):
+        return self._STOP_AND_EXIT
+
+    def get_device_mib(self, device_id, depth=-1):
+        stub = self.get_stub()
+
+        try:
+            res = stub.GetMibDeviceData(voltha_pb2.ID(id=device_id),
+                                        metadata=(('get-depth', str(depth)), ))
+        except Exception as e:
+            pass
+
+        return res
+
+    def help_show_mib(self):
+        self.poutput('show_mib [-d <device-id>] [-c <class-id> [-i <instance-id>]]' +
+                     linesep + '-d: <device-id>   ONU Device ID' +
+                     linesep + '-c: <class-id>    Managed Entity Class ID' +
+                     linesep + '-i: <instance-id> ME Instance ID')
+
+    @options([
+        make_option('-d', '--device-id', action="store", dest='device_id', type='string',
+                    help='ONU Device ID', default=None),
+        make_option('-c', '--class-id', action="store", dest='class_id',
+                    type='int', help='Managed Entity Class ID', default=None),
+        make_option('-i', '--instance-id', action="store", dest='instance_id',
+                    type='int', help='ME Instance ID', default=None)
+    ])
+    def do_show_mib(self, _line, opts):
+        """
+        Show OMCI MIB Database Information
+        """
+        device_id = opts.device_id or self.device_id
+
+        if opts.class_id is not None and not 1 <= opts.class_id <= 0xFFFF:
+            self.poutput(self.colorize('Error: ', 'red') +
+                         self.colorize('Class ID must be 1..65535', 'blue'))
+            return
+
+        if opts.instance_id is not None and opts.class_id is None:
+            self.poutput(self.colorize('Error: ', 'red') +
+                         self.colorize('Class ID required if specifying an Instance ID',
+                                       'blue'))
+            return
+
+        if opts.instance_id is not None and not 0 <= opts.instance_id <= 0xFFFF:
+            self.poutput(self.colorize('Error: ', 'red') +
+                         self.colorize('Instance ID must be 0..65535', 'blue'))
+            return
+
+        try:
+            mib_db = self.get_device_mib(device_id, depth=-1)
+
+        except Exception:   # UnboundLocalError if Device ID not found in DB
+            self.poutput(self.colorize('Failed to get MIB database for ONU {}'
+                                       .format(device_id), 'red'))
+            return
+
+        mib = self._device_to_dict(mib_db)
+
+        self.poutput('OpenOMCI MIB Database for ONU {}'.format(device_id))
+
+        if opts.class_id is None and opts.instance_id is None:
+            self.poutput('Version            : {}'.format(mib[OmciCli.VERSION_KEY]))
+            self.poutput('Created            : {}'.format(mib[OmciCli.CREATED_KEY]))
+            self.poutput('Last In-Sync Time  : {}'.format(mib[OmciCli.LAST_SYNC_KEY]))
+            self.poutput('MIB Data Sync Value: {}'.format(mib[OmciCli.MDS_KEY]))
+
+        class_ids = [k for k in mib.iterkeys()
+                     if isinstance(k, int) and
+                     (opts.class_id is None or opts.class_id == k)]
+        class_ids.sort()
+
+        if len(class_ids) == 0 and opts.class_id is not None:
+            self.poutput(self.colorize('Class ID {} not found in MIB Database'
+                                       .format(opts.class_id), 'red'))
+            return
+
+        for cls_id in class_ids:
+            class_data = mib[cls_id]
+            self.poutput('  ----------------------------------------------')
+            self.poutput('  Class ID: {0} - ({0:#x})'.format(cls_id))
+
+            inst_ids = [k for k in class_data.iterkeys()
+                        if isinstance(k, int) and
+                        (opts.instance_id is None or opts.instance_id == k)]
+            inst_ids.sort()
+
+            if len(inst_ids) == 0 and opts.instance_id is not None:
+                self.poutput(self.colorize('Instance ID {} of Class ID {} not ' +
+                                           'found in MIB Database'.
+                                           format(opts.instance_id, opts.class_id),
+                                           'red'))
+                return
+
+            for inst_id in inst_ids:
+                inst_data = class_data[inst_id]
+                self.poutput('    Instance ID: {0} - ({0:#x})'.format(inst_id))
+                self.poutput('    Created    : {}'.format(inst_data[OmciCli.CREATED_KEY]))
+                self.poutput('    Modified   : {}'.format(inst_data[OmciCli.MODIFIED_KEY]))
+
+                attributes = inst_data[OmciCli.ATTRIBUTES_KEY]
+                attr_names = attributes.keys()
+                attr_names.sort()
+                max_len = max([len(attr) for attr in attr_names])
+
+                for attr in attr_names:
+                    name = self._cleanup_attribute_name(attr).ljust(max_len)
+                    value = attributes[attr]
+                    try:
+                        ivalue = int(value)
+                        self.poutput('      {0}: {1} - ({1:#x})'.format(name, ivalue))
+
+                    except ValueError:
+                        self.poutput('      {}: {}'.format(name, value))
+
+                if inst_id is not inst_ids[-1]:
+                    self.poutput(linesep)
+
+    def _cleanup_attribute_name(self, attr):
+        """Change underscore to space and capitalize first character"""
+        return ' '.join([v[0].upper() + v[1:] for v in attr.split('_')])
+
+    def _instance_to_dict(self, instance):
+        if not isinstance(instance, MibInstanceData):
+            raise TypeError('{} is not of type MibInstanceData'.format(type(instance)))
+
+        data = {
+            OmciCli.INSTANCE_ID_KEY: instance.instance_id,
+            OmciCli.CREATED_KEY: self._string_to_time(instance.created),
+            OmciCli.MODIFIED_KEY: self._string_to_time(instance.modified),
+            OmciCli.ATTRIBUTES_KEY: dict()
+        }
+        for attribute in instance.attributes:
+            data[OmciCli.ATTRIBUTES_KEY][attribute.name] = str(attribute.value)
+
+        return data
+
+    def _class_to_dict(self, val):
+        if not isinstance(val, MibClassData):
+            raise TypeError('{} is not of type MibClassData'.format(type(val)))
+
+        data = {
+            OmciCli.CLASS_ID_KEY: val.class_id,
+        }
+        for instance in val.instances:
+            data[instance.instance_id] = self._instance_to_dict(instance)
+        return data
+
+    def _device_to_dict(self, val):
+        if not isinstance(val, MibDeviceData):
+            raise TypeError('{} is not of type MibDeviceData'.format(type(val)))
+
+        data = {
+            OmciCli.DEVICE_ID_KEY: val.device_id,
+            OmciCli.CREATED_KEY: self._string_to_time(val.created),
+            OmciCli.LAST_SYNC_KEY: self._string_to_time(val.last_sync_time),
+            OmciCli.MDS_KEY: val.mib_data_sync,
+            OmciCli.VERSION_KEY: val.version,
+            OmciCli.ME_KEY: dict(),
+            OmciCli.MSG_TYPE_KEY: set()
+        }
+        for class_data in val.classes:
+            data[class_data.class_id] = self._class_to_dict(class_data)
+
+        for managed_entity in val.managed_entities:
+            data[OmciCli.ME_KEY][managed_entity.class_id] = managed_entity.name
+
+        for msg_type in val.message_types:
+            data[OmciCli.MSG_TYPE_KEY].add(msg_type.message_type)
+
+        return data
+
+    def _string_to_time(self, time):
+        return datetime.strptime(time, OmciCli.TIME_FORMAT) if len(time) else None
+
+    def help_show_me(self):
+        self.poutput('show_me [-d <device-id>]' +
+                     linesep + '-d: <device-id>   ONU Device ID')
+
+    @options([
+        make_option('-d', '--device-id', action="store", dest='device_id', type='string',
+                    help='ONU Device ID', default=None),
+    ])
+    def do_show_me(self, _line, opts):
+        """ Show supported OMCI Managed Entities"""
+
+        device_id = opts.device_id or self.device_id
+
+        try:
+            mib_db = self.get_device_mib(device_id, depth=1)
+            mib = self._device_to_dict(mib_db)
+
+        except Exception:   # UnboundLocalError if Device ID not found in DB
+            self.poutput(self.colorize('Failed to get supported ME information for ONU {}'
+                                       .format(device_id), 'red'))
+            return
+
+        class_ids = [class_id for class_id in mib[OmciCli.ME_KEY].keys()]
+        class_ids.sort()
+
+        self.poutput('Supported Managed Entities for ONU {}'.format(device_id))
+        for class_id in class_ids:
+            self.poutput('    {0} - ({0:#x}): {1}'.format(class_id,
+                                                          mib[OmciCli.ME_KEY][class_id]))
+
+    def help_show_msg_types(self):
+        self.poutput('show_msg_types [-d <device-id>]' +
+                     linesep + '-d: <device-id>   ONU Device ID')
+
+    @options([
+        make_option('-d', '--device-id', action="store", dest='device_id', type='string',
+                    help='ONU Device ID', default=None),
+    ])
+    def do_show_msg_types(self, _line, opts):
+        """ Show supported OMCI Message Types"""
+        device_id = opts.device_id or self.device_id
+
+        try:
+            mib_db = self.get_device_mib(device_id, depth=1)
+            mib = self._device_to_dict(mib_db)
+
+        except Exception:   # UnboundLocalError if Device ID not found in DB
+            self.poutput(self.colorize('Failed to get supported Message Types for ONU {}'
+                                       .format(device_id), 'red'))
+            return
+
+        msg_types = [msg_type for msg_type in mib[OmciCli.MSG_TYPE_KEY]]
+        msg_types.sort()
+
+        self.poutput('Supported Message Types for ONU {}'.format(device_id))
+        for msg_type in msg_types:
+            self.poutput('    {0} - ({0:#x}): {1}'.
+                         format(msg_type,
+                                OmciCli.MSG_TYPE_TO_NAME.get(msg_type, 'Unknown')))
+
+    def get_devices(self):
+        stub = self.get_stub()
+        res = stub.ListDevices(Empty())
+        return res.items
+
+    def do_devices(self, line):
+        """List devices registered in Voltha reduced for OMCI menu"""
+        devices = self.get_devices()
+        omit_fields = {
+            'adapter',
+            'model',
+            'hardware_version',
+            'images',
+            'firmware_version',
+            'serial_number',
+            'vlan',
+            'root',
+            'extra_args',
+            'proxy_address',
+        }
+        print_pb_list_as_table('Devices:', devices, omit_fields, self.poutput)
+
+    def help_devices(self):
+        self.poutput('TODO: Provide some help')
+
+    def poutput(self, msg):
+        """Convenient shortcut for self.stdout.write(); adds newline if necessary."""
+        if msg:
+            self.stdout.write(msg)
+            if msg[-1] != '\n':
+                self.stdout.write('\n')
