docs: def CLI(ctx, config, list_lookups):
      """Lookup basic phone number information or send SMS messages"""
      loglevel = 'info'
      verbosity = getattr(logging, loglevel.upper(), 'INFO')
      #verbosity = logging.DEBUG
      ctx.obj = {
          'verbosity': verbosity,
          'logfile': None,
          'config': {'lookups': {}},
      }
      #logfmt = '%(levelname)-8s | %(message)s'
      logfmt = '%(message)s'
      logging.basicConfig(format=logfmt, level=verbosity)
      debug('CLI >  CWD="{0}"'.format(os.getcwd()))
      with open(CONFIG_FILE, 'ab+') as phonedb:
          phonedb.seek(0)
          rawdata = phonedb.read()
          if rawdata:
              data = json.loads(rawdata, object_pairs_hook=OrderedDict)
              debug(data)
              ctx.obj['config'] = data
              if 'lookups' not in ctx.obj['config']:
                  ctx.obj['config']['lookups'] = {}
  
      if 'sms_gateways' not in ctx.obj['config']:
          """
          gwsorted = sorted(ctx.obj['config']['sms_gateways'].items())
          gwordered = OrderedDict()
          for (k, v) in gwsorted:
              gwordered[k] = v
          ctx.obj['config']['sms_gateways'] = gwordered
          """
          info('loading SMS gateways...')
          sms_gateways = {}
          with open('carrier-gateways', 'rb') as gateways:
              gwdata = gateways.read()
              import re
              re_carrier = r'(?P<carrier>\w+[\w\&\(\)\-\'\s]*[\w\)\(]+)\s+'
              re_gateway = r'10digitphonenumber(?P<gateway>\@\w[\w\.]*\w)\s+'
              gwre = re.compile(re_carrier + re_gateway)
              gws = gwre.findall(gwdata)
              for gw in gwre.finditer(gwdata):
                  gwinfo = gw.groupdict()
                  debug(gw.groupdict())
                  sms_gateways[gwinfo['carrier']] = gwinfo['gateway']
              num_lines = len([l for l in gwdata.split('\n') if len(l)])
              debug('lines={0} ({1} / 2)'.format(num_lines/2, num_lines))
              debug('matches={0}'.format(len(data)))
          ctx.obj['config']['sms_gateways'] = sms_gateways
          with open(CONFIG_FILE, 'wb') as cfg:
              cfg.write(json.dumps(ctx.obj['config'], indent=2))
          info('SMS gateways written to config')
  
      if list_lookups:
          sms_updated = False
          from fuzzywuzzy import fuzz
          from fuzzywuzzy import process
          lookups = ctx.obj['config']['lookups']
          info('cached lookups:')
          for number, pinfo in lookups.iteritems():
              owner = pinfo['comment']
              common = pinfo['body']['national_format']
              carrier = pinfo['body']['carrier']['name']
              pntype = pinfo['body']['carrier']['type']
              info('  {0}: {1}'.format(owner, common))
              info('    - carrier: {0}'.format(carrier))
              info('    - type: {0}'.format(pntype))
              debug('    - unformatted: {0}'.format(number))
              if 'sms' not in lookups[number]:
                  carriers = ctx.obj['config']['sms_gateways'].keys()
                  fuzzy = process.extract(carrier, carriers)
                  fuzz_max = 0
                  result = []
                  gateway_key = None
                  for f in fuzzy:
                      if f[1] >= fuzz_max:
                          fuzz_max = f[1]
                          result.append(f[0])
                  debug(result)
                  if len(result) > 1:
                      if len(sorted(result)[0]) <= len(carrier):
                          gateway_key = sorted(result)[0]
                      else:
                          gateway_key = result[0]
                  else:
                      gateway_key = result[0]
                  gw_suffix = ctx.obj['config']['sms_gateways'][gateway_key]
                  ctx.obj['config']['lookups'][number]['sms'] = '{0}{1}'.format(
                      number, gw_suffix)
                  sms_updated = True
              info('    - SMS gateway: {0}'.format(
                  ctx.obj['config']['lookups'][number]['sms']))
          if sms_updated:
              with open(CONFIG_FILE, 'wb') as cfg:
                  cfg.write(json.dumps(ctx.obj['config'], indent=2))
          ctx.exit()