diff --git a/py-dashboard/GhostRequest.py b/py-dashboard/GhostRequest.py
index a8a10219..5aa483aa 100644
--- a/py-dashboard/GhostRequest.py
+++ b/py-dashboard/GhostRequest.py
@@ -1,8 +1,10 @@
 #!/usr/bin/env python3
 
 # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-# Class holds default settings for json requests to Grafana     -
+# Class holds default settings for json requests to Ghost     -
 # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+import ast
+import os
 import sys
 
 if sys.version_info[0] != 3:
@@ -13,25 +15,69 @@ import requests
 
 import jwt
 from datetime import datetime as date
+import json
+import subprocess
+from scp import SCPClient
+import paramiko
+
+
+class CSVReader:
+    def read_csv(self,
+                 file,
+                 sep=','):
+        csv = open(file).read().split('\n')
+        rows = list()
+        for x in csv:
+            if len(x) > 0:
+                rows.append(x.split(sep))
+        length = list(range(0, len(df[0])))
+        columns = dict(zip(df[0], length))
+        return rows
+
+    def get_column(df, value):
+        index = df[0].index(value)
+        values = []
+        for row in df[1:]:
+            values.append(row[index])
+        return values
 
 
 class GhostRequest:
     def __init__(self,
-                 _ghostjson_host,
-                 _ghostjson_port,
+                 _ghost_json_host,
+                 _ghost_json_port,
                  _api_token=None,
-                 _headers=dict(),
                  _overwrite='false',
                  debug_=False,
                  die_on_error_=False):
         self.debug = debug_
         self.die_on_error = die_on_error_
-        self.ghostjson_url = "http://%s:%s/ghost/api/v3" % (_ghostjson_host, _ghostjson_port)
+        self.ghost_json_host = _ghost_json_host
+        self.ghost_json_port = _ghost_json_port
+        self.ghost_json_url = "http://%s:%s/ghost/api/v3" % (_ghost_json_host, _ghost_json_port)
         self.data = dict()
         self.data['overwrite'] = _overwrite
-        self.ghostjson_login = self.ghostjson_url + '/admin/session/'
+        self.ghost_json_login = self.ghost_json_url + '/admin/session/'
         self.api_token = _api_token
+        self.images = list()
+        self.pdfs = list()
 
+    def encode_token(self):
+
+        # Split the key into ID and SECRET
+        key_id, secret = self.api_token.split(':')
+
+        # Prepare header and payload
+        iat = int(date.now().timestamp())
+
+        header = {'alg': 'HS256', 'typ': 'JWT', 'kid': key_id}
+        payload = {
+            'iat': iat,
+            'exp': iat + 5 * 60,
+            'aud': '/v3/admin/'
+        }
+        token = jwt.encode(payload, bytes.fromhex(secret), algorithm='HS256', headers=header)
+        return token
 
     def create_post(self,
                     title=None,
@@ -39,15 +85,7 @@ class GhostRequest:
                     tags=None,
                     authors=None,
                     status="published"):
-        ghostjson_url = self.ghostjson_url + '/admin/posts/'
-        datastore = dict()
-        datastore['title'] = title
-        if tags is not None:
-            datastore['tags'] = tags
-        if authors is not None:
-            datastore['authors'] = authors
-        datastore['html'] = text
-        datastore['status'] = status
+        ghost_json_url = self.ghost_json_url + '/admin/posts/?source=html'
         post = dict()
         posts = list()
         datastore = dict()
@@ -59,18 +97,132 @@ class GhostRequest:
 
         headers = dict()
 
-        # Split the key into ID and SECRET
-        id, secret = self.api_token.split(':')
-
-        # Prepare header and payload
-        iat = int(date.now().timestamp())
-
-        header = {'alg': 'HS256', 'typ': 'JWT', 'kid': id}
-        payload = {
-            'iat': iat,
-            'exp': iat + 5 * 60,
-            'aud': '/v3/admin/'
-        }
-        token = jwt.encode(payload, bytes.fromhex(secret), algorithm='HS256', headers=header)
+        token = self.encode_token()
         headers['Authorization'] = 'Ghost {}'.format(token)
-        requests.post(ghostjson_url, json=post, headers=headers)
+        response = requests.post(ghost_json_url, json=post, headers=headers)
+        if self.debug:
+            print(datastore)
+            print(ghost_json_url)
+            print('\n')
+            print(post)
+            print('\n')
+            print(headers)
+            print(response.headers)
+
+    def upload_image(self,
+                     image):
+        print(image)
+        ghost_json_url = self.ghost_json_url + '/admin/images/upload/'
+
+        token = self.encode_token()
+        bashCommand = "curl -X POST -F 'file=@%s' -H \"Authorization: Ghost %s\" %s" % (image, token, ghost_json_url)
+
+        proc = subprocess.Popen(bashCommand, shell=True, stdout=subprocess.PIPE)
+        output = proc.stdout.read().decode('utf-8')
+        print(output)
+        self.images.append(json.loads(output)['images'][0]['url'])
+
+    def upload_images(self,
+                      folder):
+        for image in os.listdir(folder):
+            if 'kpi' in image:
+                if 'png' in image:
+                    self.upload_image(folder + '/' + image)
+        print('images %s' % self.images)
+
+    def custom_post(self,
+                    folder,
+                    authors,
+                    title='custom'):
+        self.upload_images(folder)
+        head = '''
This is a custom post created via a script
'''
+        for picture in self.images:
+            head = head + ' ' % picture
+        head = head + '''
' % picture
+        head = head + '''This is the end of the example
'''
+        self.create_post(title=title,
+                         text=head,
+                         tags='custom',
+                         authors=authors)
+
+    def wifi_capacity_to_ghost(self,
+                               authors,
+                               folders,
+                               title='Wifi Capacity',
+                               server_pull=None,
+                               ghost_host=None,
+                               port='22',
+                               user_pull='lanforge',
+                               password_pull='lanforge',
+                               user_push=None,
+                               password_push=None,
+                               customer=None,
+                               testbed=None,
+                               test_run=None):
+        text = '''The Candela WiFi Capacity test is designed to measure performance of an Access Point when handling 
+        different amounts of WiFi Stations. The test allows the user to increase the number of stations in user 
+        defined steps for each test iteration and measure the per station and the overall throughput for each trial. 
+        Along with throughput other measurements made are client connection times, Fairness, % packet loss, 
+        DHCP times and more. The expected behavior is for the AP to be able to handle several stations (within the 
+        limitations of the AP specs) and make sure all stations get a fair amount of airtime both in the upstream and 
+        downstream. An AP that scales well will not show a significant over-all throughput decrease as more stations 
+        are added. 
+        Realtime Graph shows summary download and upload RX bps of connections created by this test.
'''
+
+        if test_run is None:
+            test_run = sorted(folders)[0].split('/')[-1]
+        for folder in folders:
+            ssh_pull = paramiko.SSHClient()
+            ssh_pull.set_missing_host_key_policy(paramiko.client.AutoAddPolicy)
+            ssh_pull.connect(server_pull,
+                             port,
+                             username=user_pull,
+                             password=password_pull,
+                             allow_agent=False,
+                             look_for_keys=False)
+            scp_pull = SCPClient(ssh_pull.get_transport())
+            scp_pull.get(folder, recursive=True)
+            ssh_push = paramiko.SSHClient()
+            ssh_push.set_missing_host_key_policy(paramiko.client.AutoAddPolicy)
+            ssh_push.connect(ghost_host,
+                             port,
+                             username=user_push,
+                             password=password_push,
+                             allow_agent=False,
+                             look_for_keys=False)
+            scp_push = SCPClient(ssh_push.get_transport())
+            local_path = '/home/%s/%s/%s/%s' % (user_push, customer, testbed, test_run)
+            transport = paramiko.Transport((ghost_host, port))
+            transport.connect(None, user_push, password_push)
+            sftp = paramiko.sftp_client.SFTPClient.from_transport(transport)
+            print(local_path)
+            sftp.mkdir(local_path)
+            target_folder = folder.split('/')[-1]
+            print(target_folder)
+            scp_push.put(target_folder, recursive=True, remote_path=local_path)
+            files = sftp.listdir(local_path + '/' + target_folder)
+            print('Files: %s' % files)
+            for file in files:
+                if 'pdf' in file:
+                    self.pdfs.append(file)
+
+            #df = CSVReader.read_csv(local_path + '/' + target_folder + '/' + 'kpi.csv')
+            #testbed = CSVReader.get_column(df, 'test-rig')[0]
+
+            print('PDFs %s' % self.pdfs)
+            scp_pull.close()
+            scp_push.close()
+            self.upload_images(target_folder)
+
+        for pdf in self.pdfs:
+            url = 'http://%s/%s/%s/%s/%s/%s' % (ghost_host, customer, testbed, test_run, target_folder, pdf)
+            text = text + 'PDF of results: %s' % (url, url)
+
+        for image in self.images:
+            if 'kpi-' in image:
+                if '-print' not in image:
+                    text = text + ' ' % image
+
+        self.create_post(title=title,
+                         text=text,
+                         tags='custom',
+                         authors=authors)
diff --git a/py-scripts/ghost_profile.py b/py-scripts/ghost_profile.py
index 996dd82b..824eab1c 100755
--- a/py-scripts/ghost_profile.py
+++ b/py-scripts/ghost_profile.py
@@ -6,6 +6,14 @@ PURPOSE: modify ghost database from the command line.
 SETUP: A Ghost installation which the user has admin access to.
 EXAMPLE: ./ghost_profile.py --article_text_file text.txt --title Test --authors Matthew --ghost_token SECRET_KEY --host 192.168.1.1
 
+There is a specific class for uploading wifi capacity graphs called wifi_capacity.
+
+EXAMPLE: ./ghost_profile.py --ghost_token TOKEN --ghost_host 192.168.100.147
+--folders /home/lanforge/html-reports/wifi-capacity-2021-06-04-02-51-07
+--wifi_capacity appl --authors Matthew --title 'wifi capacity 2021 06 04 02 51 07' --server 192.168.93.51
+--user_pull lanforge --password_pull lanforge --customer candela --testbed heather --test_run test-run-6
+--user_push matt --password_push PASSWORD
+
  Matthew Stidham
  Copyright 2021 Candela Technologies Inc
     License: Free to distribute and modify. LANforge systems must be licensed.
@@ -23,9 +31,9 @@ if 'py-json' not in sys.path:
     sys.path.append(os.path.join(os.path.abspath('..'), 'py-dashboard'))
 
 from GhostRequest import GhostRequest
-from LANforge.lfcli_base import LFCliBase
 
-class UseGhost(LFCliBase):
+
+class UseGhost():
     def __init__(self,
                  _ghost_token=None,
                  host="localhost",
@@ -34,11 +42,13 @@ class UseGhost(LFCliBase):
                  _exit_on_fail=False,
                  _ghost_host="localhost",
                  _ghost_port=2368, ):
-        super().__init__(host, port, _debug=_debug_on, _exit_on_fail=_exit_on_fail)
         self.ghost_host = _ghost_host
         self.ghost_port = _ghost_port
         self.ghost_token = _ghost_token
-        self.GP = GhostRequest(self.ghost_host, str(self.ghost_port), _api_token=self.ghost_token)
+        self.GP = GhostRequest(self.ghost_host,
+                               str(self.ghost_port),
+                               _api_token=self.ghost_token,
+                               debug_=_debug_on)
 
     def create_post(self, title, text, tags, authors):
         return self.GP.create_post(title=title, text=text, tags=tags, authors=authors)
@@ -47,9 +57,46 @@ class UseGhost(LFCliBase):
         text = open(file).read()
         return self.GP.create_post(title=title, text=text, tags=tags, authors=authors)
 
+    def upload_image(self, image):
+        return self.GP.upload_image(image)
+
+    def upload_images(self, folder):
+        return self.GP.upload_images(folder)
+
+    def custom_post(self, folder, authors):
+        return self.GP.custom_post(folder, authors)
+
+    def wifi_capacity(self,
+                      authors,
+                      folders,
+                      title,
+                      server_pull,
+                      ghost_host,
+                      port,
+                      user_pull,
+                      password_pull,
+                      user_push,
+                      password_push,
+                      customer,
+                      testbed,
+                      test_run):
+        return self.GP.wifi_capacity_to_ghost(authors,
+                                              folders,
+                                              title,
+                                              server_pull,
+                                              ghost_host,
+                                              port,
+                                              user_pull,
+                                              password_pull,
+                                              user_push,
+                                              password_push,
+                                              customer,
+                                              testbed,
+                                              test_run)
+
 
 def main():
-    parser = LFCliBase.create_basic_argparse(
+    parser = argparse.ArgumentParser(
         prog='ghost_profile.py',
         formatter_class=argparse.RawTextHelpFormatter,
         epilog='''Manage Ghost Website''',
@@ -71,17 +118,60 @@ def main():
     optional.add_argument('--article_tags', action='append')
     optional.add_argument('--authors', action='append')
     optional.add_argument('--title', default=None)
+    optional.add_argument('--image', default=None)
+    optional.add_argument('--folder', default=None)
+    optional.add_argument('--custom_post', default=None)
+    optional.add_argument('--wifi_capacity', default=None)
+    optional.add_argument('--folders', action='append', default=None)
+    optional.add_argument('--server_pull')
+    optional.add_argument('--port', default=22)
+    optional.add_argument('--user_pull', default='lanforge')
+    optional.add_argument('--password_pull', default='lanforge')
+    optional.add_argument('--user_push')
+    optional.add_argument('--password_push')
+    optional.add_argument('--customer')
+    optional.add_argument('--testbed')
+    optional.add_argument('--test_run', default=None)
+    optional.add_argument('--debug')
     args = parser.parse_args()
 
     Ghost = UseGhost(_ghost_token=args.ghost_token,
                      _ghost_port=args.ghost_port,
-                     _ghost_host=args.ghost_host)
+                     _ghost_host=args.ghost_host,
+                     _debug_on=args.debug)
 
     if args.create_post is not None:
         Ghost.create_post(args.title, args.article_text, args.article_tags, args.authors)
     if args.article_text_file is not None:
         Ghost.create_post_from_file(args.title, args.article_text_file, args.article_tags, args.authors)
 
+    if args.image is not None:
+        Ghost.upload_image(args.image)
+
+    if args.custom_post is not None:
+        if args.folders is not None:
+            Ghost.custom_post(args.folders, args.authors)
+        else:
+            Ghost.custom_post(args.folder, args.authors)
+    else:
+        if args.folder is not None:
+            Ghost.upload_images(args.folder)
+
+    if args.wifi_capacity is not None:
+        Ghost.wifi_capacity(args.authors,
+                            args.folders,
+                            args.title,
+                            args.server_pull,
+                            args.ghost_host,
+                            args.port,
+                            args.user_pull,
+                            args.password_pull,
+                            args.user_push,
+                            args.password_push,
+                            args.customer,
+                            args.testbed,
+                            args.test_run)
+
 
 if __name__ == "__main__":
     main()
' % image
+
+        self.create_post(title=title,
+                         text=text,
+                         tags='custom',
+                         authors=authors)
diff --git a/py-scripts/ghost_profile.py b/py-scripts/ghost_profile.py
index 996dd82b..824eab1c 100755
--- a/py-scripts/ghost_profile.py
+++ b/py-scripts/ghost_profile.py
@@ -6,6 +6,14 @@ PURPOSE: modify ghost database from the command line.
 SETUP: A Ghost installation which the user has admin access to.
 EXAMPLE: ./ghost_profile.py --article_text_file text.txt --title Test --authors Matthew --ghost_token SECRET_KEY --host 192.168.1.1
 
+There is a specific class for uploading wifi capacity graphs called wifi_capacity.
+
+EXAMPLE: ./ghost_profile.py --ghost_token TOKEN --ghost_host 192.168.100.147
+--folders /home/lanforge/html-reports/wifi-capacity-2021-06-04-02-51-07
+--wifi_capacity appl --authors Matthew --title 'wifi capacity 2021 06 04 02 51 07' --server 192.168.93.51
+--user_pull lanforge --password_pull lanforge --customer candela --testbed heather --test_run test-run-6
+--user_push matt --password_push PASSWORD
+
  Matthew Stidham
  Copyright 2021 Candela Technologies Inc
     License: Free to distribute and modify. LANforge systems must be licensed.
@@ -23,9 +31,9 @@ if 'py-json' not in sys.path:
     sys.path.append(os.path.join(os.path.abspath('..'), 'py-dashboard'))
 
 from GhostRequest import GhostRequest
-from LANforge.lfcli_base import LFCliBase
 
-class UseGhost(LFCliBase):
+
+class UseGhost():
     def __init__(self,
                  _ghost_token=None,
                  host="localhost",
@@ -34,11 +42,13 @@ class UseGhost(LFCliBase):
                  _exit_on_fail=False,
                  _ghost_host="localhost",
                  _ghost_port=2368, ):
-        super().__init__(host, port, _debug=_debug_on, _exit_on_fail=_exit_on_fail)
         self.ghost_host = _ghost_host
         self.ghost_port = _ghost_port
         self.ghost_token = _ghost_token
-        self.GP = GhostRequest(self.ghost_host, str(self.ghost_port), _api_token=self.ghost_token)
+        self.GP = GhostRequest(self.ghost_host,
+                               str(self.ghost_port),
+                               _api_token=self.ghost_token,
+                               debug_=_debug_on)
 
     def create_post(self, title, text, tags, authors):
         return self.GP.create_post(title=title, text=text, tags=tags, authors=authors)
@@ -47,9 +57,46 @@ class UseGhost(LFCliBase):
         text = open(file).read()
         return self.GP.create_post(title=title, text=text, tags=tags, authors=authors)
 
+    def upload_image(self, image):
+        return self.GP.upload_image(image)
+
+    def upload_images(self, folder):
+        return self.GP.upload_images(folder)
+
+    def custom_post(self, folder, authors):
+        return self.GP.custom_post(folder, authors)
+
+    def wifi_capacity(self,
+                      authors,
+                      folders,
+                      title,
+                      server_pull,
+                      ghost_host,
+                      port,
+                      user_pull,
+                      password_pull,
+                      user_push,
+                      password_push,
+                      customer,
+                      testbed,
+                      test_run):
+        return self.GP.wifi_capacity_to_ghost(authors,
+                                              folders,
+                                              title,
+                                              server_pull,
+                                              ghost_host,
+                                              port,
+                                              user_pull,
+                                              password_pull,
+                                              user_push,
+                                              password_push,
+                                              customer,
+                                              testbed,
+                                              test_run)
+
 
 def main():
-    parser = LFCliBase.create_basic_argparse(
+    parser = argparse.ArgumentParser(
         prog='ghost_profile.py',
         formatter_class=argparse.RawTextHelpFormatter,
         epilog='''Manage Ghost Website''',
@@ -71,17 +118,60 @@ def main():
     optional.add_argument('--article_tags', action='append')
     optional.add_argument('--authors', action='append')
     optional.add_argument('--title', default=None)
+    optional.add_argument('--image', default=None)
+    optional.add_argument('--folder', default=None)
+    optional.add_argument('--custom_post', default=None)
+    optional.add_argument('--wifi_capacity', default=None)
+    optional.add_argument('--folders', action='append', default=None)
+    optional.add_argument('--server_pull')
+    optional.add_argument('--port', default=22)
+    optional.add_argument('--user_pull', default='lanforge')
+    optional.add_argument('--password_pull', default='lanforge')
+    optional.add_argument('--user_push')
+    optional.add_argument('--password_push')
+    optional.add_argument('--customer')
+    optional.add_argument('--testbed')
+    optional.add_argument('--test_run', default=None)
+    optional.add_argument('--debug')
     args = parser.parse_args()
 
     Ghost = UseGhost(_ghost_token=args.ghost_token,
                      _ghost_port=args.ghost_port,
-                     _ghost_host=args.ghost_host)
+                     _ghost_host=args.ghost_host,
+                     _debug_on=args.debug)
 
     if args.create_post is not None:
         Ghost.create_post(args.title, args.article_text, args.article_tags, args.authors)
     if args.article_text_file is not None:
         Ghost.create_post_from_file(args.title, args.article_text_file, args.article_tags, args.authors)
 
+    if args.image is not None:
+        Ghost.upload_image(args.image)
+
+    if args.custom_post is not None:
+        if args.folders is not None:
+            Ghost.custom_post(args.folders, args.authors)
+        else:
+            Ghost.custom_post(args.folder, args.authors)
+    else:
+        if args.folder is not None:
+            Ghost.upload_images(args.folder)
+
+    if args.wifi_capacity is not None:
+        Ghost.wifi_capacity(args.authors,
+                            args.folders,
+                            args.title,
+                            args.server_pull,
+                            args.ghost_host,
+                            args.port,
+                            args.user_pull,
+                            args.password_pull,
+                            args.user_push,
+                            args.password_push,
+                            args.customer,
+                            args.testbed,
+                            args.test_run)
+
 
 if __name__ == "__main__":
     main()