diff --git a/cmd/gosdn-tview/app/app.go b/cmd/gosdn-tview/app/app.go
new file mode 100644
index 0000000000000000000000000000000000000000..e65af13c574abbc01551afc45e88323d4b36c2da
--- /dev/null
+++ b/cmd/gosdn-tview/app/app.go
@@ -0,0 +1,50 @@
+package app
+
+import "github.com/rivo/tview"
+
+type view interface {
+	GetContent() tview.Primitive
+}
+
+type App struct {
+	app   *tview.Application
+	pages *tview.Pages
+}
+
+func NewApp() *App {
+	a := &App{
+		app: tview.NewApplication(),
+	}
+	return a
+}
+
+func (a *App) SetRoot(v view) {
+	a.pages = v.GetContent().(*tview.Pages)
+	a.app.SetRoot(a.pages, true)
+}
+
+func (a *App) SwitchPage(s string) {
+	if a.pages.HasPage(s) {
+		a.pages.SwitchToPage(s)
+	}
+}
+
+func (a *App) AddPage(name string, p view) {
+	a.pages.AddPage(name, p.GetContent(), true, false)
+}
+
+func (a *App) Run() error {
+	return a.app.Run()
+}
+
+func (a *App) Stop() {
+	a.app.Stop()
+}
+
+func (a *App) Draw() {
+	a.app.Draw()
+}
+
+func (a *App) SetFocus(v tview.Primitive) {
+	a.app.SetFocus(v)
+}
diff --git a/cmd/gosdn-tview/grpc/commands.go b/cmd/gosdn-tview/grpc/commands.go
new file mode 100644
index 0000000000000000000000000000000000000000..6eabf835326dcf0a08663bec21632fbc09384744
--- /dev/null
+++ b/cmd/gosdn-tview/grpc/commands.go
@@ -0,0 +1,125 @@
+package commands
+
+import (
+	pb "code.fbi.h-da.de/cocsn/gosdn/api/proto"
+	"code.fbi.h-da.de/cocsn/gosdn/log"
+	"context"
+	grpc "google.golang.org/grpc"
+	"time"
+)
+
+type commandType int
+
+const (
+	GoSDN commandType = iota
+	Database
+)
+
+const (
+	defaultName = "gosdn-cli"
+)
+
+type command struct {
+	Name        string
+	Description string
+	//CommandType commandType
+	Function func(conn *grpc.ClientConn) string
+}
+
+var CommandList = []command{
+	{"hello", "test connection to goSDN controller", goSDNSayHello},
+	{"shutdown", "request goSDN controller to shutdown", goSDNShutdown},
+	{"testdb", "test all database connections", goSDNTestDB},
+	{"tapigetedge", "get list of edges", TAPIGetEdge},
+	{"tapigetedgenode", "get list of edgenodes", TAPIGetEdgeNode},
+	{"tapigetlink", "get list of links", TAPIGetLink},
+}
+
+func Connect() (*grpc.ClientConn, error) {
+	address := "localhost:55055"
+	return grpc.Dial(address, grpc.WithInsecure(), grpc.WithTimeout(5*time.Second), grpc.WithBlock())
+}
+
+func goSDNSayHello(conn *grpc.ClientConn) string {
+	c := pb.NewGrpcCliClient(conn)
+
+	// Contact the server and print out its response.
+	name := defaultName
+	ctx, cancel := context.WithTimeout(context.Background(), time.Second)
+	defer cancel()
+	r, err := c.SayHello(ctx, &pb.HelloRequest{Name: name})
+	if err != nil {
+		log.Fatal(err)
+	}
+	return r.GetMessage()
+}
+
+func goSDNShutdown(conn *grpc.ClientConn) string {
+
+	c := pb.NewGrpcCliClient(conn)
+
+	// Contact the server and print out its response.
+	name := defaultName
+	ctx, cancel := context.WithTimeout(context.Background(), time.Second)
+	defer cancel()
+	r, err := c.Shutdown(ctx, &pb.ShutdownRequest{Name: name})
+	if err != nil {
+		log.Fatal(err)
+	}
+	return r.GetMessage()
+}
+
+func goSDNTestDB(conn *grpc.ClientConn) string {
+	// TODO: fill with code and also see if grpc interface has this stub implemented.
+	return "not implemented yet"
+}
+
+// TAPIGetEdge triggers the GetEdge function of the Ciena
+// flavoured TAPI client
+func TAPIGetEdge(conn *grpc.ClientConn) string {
+
+	c := pb.NewGrpcCliClient(conn)
+
+	// Contact the server and print out its response.
+	name := defaultName
+	ctx, cancel := context.WithTimeout(context.Background(), time.Second)
+	defer cancel()
+	r, err := c.TAPIGetEdge(ctx, &pb.TAPIRequest{Name: name})
+	if err != nil {
+		log.Fatal(err)
+	}
+	return r.GetMessage()
+}
+
+// TAPIGetEdgeNode triggers the GetEdgeNode function of the Ciena
+// flavoured TAPI client
+func TAPIGetEdgeNode(conn *grpc.ClientConn) string {
+	c := pb.NewGrpcCliClient(conn)
+
+	// Contact the server and print out its response.
+	name := defaultName
+	ctx, cancel := context.WithTimeout(context.Background(), time.Second)
+	defer cancel()
+	r, err := c.TAPIGetEdgeNode(ctx, &pb.TAPIRequest{Name: name})
+	if err != nil {
+		log.Fatal(err)
+	}
+	return r.GetMessage()
+}
+
+// TAPIGetLink triggers the GetLink function of the Ciena
+// flavoured TAPI client
+func TAPIGetLink(conn *grpc.ClientConn) string {
+
+	c := pb.NewGrpcCliClient(conn)
+
+	// Contact the server and print out its response.
+	name := defaultName
+	ctx, cancel := context.WithTimeout(context.Background(), time.Second)
+	defer cancel()
+	r, err := c.TAPIGetLink(ctx, &pb.TAPIRequest{Name: name})
+	if err != nil {
+		log.Fatal(err)
+	}
+	return r.GetMessage()
+}
diff --git a/cmd/gosdn-tview/main.go b/cmd/gosdn-tview/main.go
new file mode 100644
index 0000000000000000000000000000000000000000..7f7368547959d5f92ebb922528b79d4214a2420b
--- /dev/null
+++ b/cmd/gosdn-tview/main.go
@@ -0,0 +1,23 @@
+package main
+
+import (
+	"code.fbi.h-da.de/cocsn/gosdn/cmd/gosdn-tview/app"
+	grpc "code.fbi.h-da.de/cocsn/gosdn/cmd/gosdn-tview/grpc"
+	"code.fbi.h-da.de/cocsn/gosdn/cmd/gosdn-tview/views"
+	"code.fbi.h-da.de/cocsn/gosdn/log"
+)
+
+func main() {
+	conn, err := grpc.Connect()
+	if err != nil {
+		log.Fatal(err)
+	}
+
+	app := app.NewApp()
+	mainView := views.NewMainView(app, conn)
+
+	app.SetRoot(mainView)
+
+	app.Run()
+	defer app.Stop()
+}
diff --git a/cmd/gosdn-tview/views/addPNDView.go b/cmd/gosdn-tview/views/addPNDView.go
new file mode 100644
index 0000000000000000000000000000000000000000..7fdf756110624cfc519a5be7596981c828e8a28c
--- /dev/null
+++ b/cmd/gosdn-tview/views/addPNDView.go
@@ -0,0 +1,39 @@
+package views
+
+import (
+	"code.fbi.h-da.de/cocsn/gosdn/cmd/gosdn-tview/app"
+	"github.com/rivo/tview"
+)
+
+type AddPNDView struct {
+	addPNDView *tview.Form
+}
+
+func NewAddPNDView(app *app.App) *AddPNDView {
+	pndv := &AddPNDView{
+		addPNDView: tview.NewForm(),
+	}
+	pndv.addPNDView.
+		SetBorder(true).
+		SetTitle("Add new PND")
+
+	pndv.addPNDView.
+		AddInputField("Name", "", 20, nil, nil).
+		AddInputField("description", "", 20, nil, nil).
+		AddDropDown("SI", []string{"Southbound 1", "Southbound 2", "Southbound 3", "Southbound 4"}, 0, nil).
+		AddButton("Send", func() {
+			//TODO: call grpc function here
+		}).
+		AddButton("Abort", func() {
+			app.SwitchPage("main")
+		}).
+		SetCancelFunc(func() {
+			app.SwitchPage("main")
+		})
+
+	return pndv
+}
+
+func (pndv *AddPNDView) GetContent() tview.Primitive {
+	return pndv.addPNDView
+}
diff --git a/cmd/gosdn-tview/views/commandsListView.go b/cmd/gosdn-tview/views/commandsListView.go
new file mode 100644
index 0000000000000000000000000000000000000000..2ab3f9452f436669a7f75c536a9775f68b29590a
--- /dev/null
+++ b/cmd/gosdn-tview/views/commandsListView.go
@@ -0,0 +1,50 @@
+package views
+
+import (
+	"code.fbi.h-da.de/cocsn/gosdn/cmd/gosdn-tview/app"
+	commands "code.fbi.h-da.de/cocsn/gosdn/cmd/gosdn-tview/grpc"
+	"github.com/rivo/tview"
+	"google.golang.org/grpc"
+)
+
+type CommandListView struct {
+	commandsList *tview.List
+}
+
+func NewCommandListView() *CommandListView {
+	cv := &CommandListView{
+		commandsList: tview.NewList(),
+	}
+	cv.commandsList.
+		SetBorder(true).
+		SetTitle("Commands")
+
+	return cv
+}
+
+func (cv *CommandListView) GetContent() tview.Primitive {
+	return cv.commandsList
+}
+
+func (cv *CommandListView) GetCommands(app *app.App, rv *ResultAndInputView,
+	conn *grpc.ClientConn) {
+	//TODO: create own command in grpc -> commands
+	cv.commandsList.AddItem("AddPND", "closes the application", '!', func() {
+		rv.ChangeContentView("addPND")
+		app.SetFocus(rv.GetContent())
+	})
+
+	for i, command := range commands.CommandList {
+		f := command.Function
+		cv.commandsList.
+			AddItem(command.Name, command.Description, rune('a'+i), func() {
+				r := f(conn)
+				rv.SetContent(r)
+				rv.ChangeContentView("result")
+			})
+	}
+
+	cv.commandsList.AddItem("quit", "closes the application", 'q', func() {
+		app.Stop()
+	})
+}
diff --git a/cmd/gosdn-tview/views/datbaseStatusView.go b/cmd/gosdn-tview/views/datbaseStatusView.go
new file mode 100644
index 0000000000000000000000000000000000000000..2e9a268666a054fab89b5ddef1ed28dc6c65385f
--- /dev/null
+++ b/cmd/gosdn-tview/views/datbaseStatusView.go
@@ -0,0 +1,43 @@
+package views
+
+import (
+	"code.fbi.h-da.de/cocsn/gosdn/cmd/gosdn-tview/app"
+	"github.com/rivo/tview"
+	"time"
+)
+
+type DatabaseStatusView struct {
+	databaseStatusView *tview.TextView
+}
+
+func NewDatabaseStatusView(app *app.App) *DatabaseStatusView {
+	dv := &DatabaseStatusView{
+		databaseStatusView: tview.NewTextView(),
+	}
+	dv.databaseStatusView.
+		SetDynamicColors(true).
+		SetTextAlign(tview.AlignCenter).
+		SetRegions(true).
+		SetBorder(true).
+		SetTitle("Database")
+
+	go databaseTicker(dv)
+
+	return dv
+}
+
+func (dv *DatabaseStatusView) GetContent() tview.Primitive {
+	return dv.databaseStatusView
+}
+
+func (dv *DatabaseStatusView) SetContent(s string) {
+	dv.databaseStatusView.Clear()
+	dv.databaseStatusView.SetText(s)
+}
+
+func databaseTicker(dv *DatabaseStatusView) {
+	ticker := time.NewTicker(5 * time.Second)
+	for t := range ticker.C {
+		dv.SetContent(t.String())
+	}
+}
diff --git a/cmd/gosdn-tview/views/footerView.go b/cmd/gosdn-tview/views/footerView.go
new file mode 100644
index 0000000000000000000000000000000000000000..f998d7ba5e973a3233f0b00c1c2ff880697e531c
--- /dev/null
+++ b/cmd/gosdn-tview/views/footerView.go
@@ -0,0 +1,35 @@
+package views
+
+import (
+	"code.fbi.h-da.de/cocsn/gosdn/cmd/gosdn-tview/app"
+	"github.com/rivo/tview"
+	"google.golang.org/grpc"
+)
+
+type FooterView struct {
+	footerView         *tview.Flex
+	databaseStatusView *DatabaseStatusView
+	gRPCStatusView     *GRPCStatusView
+}
+
+func NewFooterView(app *app.App, conn *grpc.ClientConn) *FooterView {
+
+	fw := &FooterView{
+		footerView:         tview.NewFlex(),
+		databaseStatusView: NewDatabaseStatusView(app),
+		gRPCStatusView:     NewGRPCStatusView(app, conn),
+	}
+	fw.footerView.
+		SetBorder(true).
+		SetTitle("Status")
+
+	fw.footerView.
+		AddItem(fw.gRPCStatusView.GetContent(), 0, 1, false).
+		AddItem(fw.databaseStatusView.GetContent(), 0, 1, false)
+
+	return fw
+}
+
+func (fw *FooterView) GetContent() tview.Primitive {
+	return fw.footerView
+}
diff --git a/cmd/gosdn-tview/views/gRPCStatusView.go b/cmd/gosdn-tview/views/gRPCStatusView.go
new file mode 100644
index 0000000000000000000000000000000000000000..3e522db7f18237e8533970fdf29f98233b6aff0e
--- /dev/null
+++ b/cmd/gosdn-tview/views/gRPCStatusView.go
@@ -0,0 +1,56 @@
+package views
+
+import (
+	"code.fbi.h-da.de/cocsn/gosdn/cmd/gosdn-tview/app"
+	"github.com/rivo/tview"
+	"google.golang.org/grpc"
+	"time"
+)
+
+type GRPCStatusView struct {
+	gRPCStatusView *tview.TextView
+}
+
+func NewGRPCStatusView(app *app.App, conn *grpc.ClientConn) *GRPCStatusView {
+	sv := &GRPCStatusView{
+		gRPCStatusView: tview.NewTextView(),
+	}
+
+	sv.gRPCStatusView.
+		SetDynamicColors(true).
+		SetTextAlign(tview.AlignCenter).
+		SetRegions(true).
+		SetBorder(true).
+		SetTitle("gRPC")
+
+	//TODO: maybe there is another way to do this.
+	//		pretty ugly atm, since it re-draws every 5 seconds...
+	sv.gRPCStatusView.SetChangedFunc(func() {
+		app.Draw()
+	})
+
+	go gRPCTicker(sv, conn)
+
+	return sv
+}
+
+func (sv *GRPCStatusView) GetContent() tview.Primitive {
+	return sv.gRPCStatusView
+}
+
+func (sv *GRPCStatusView) SetContent(s string) {
+	sv.gRPCStatusView.Clear()
+	sv.gRPCStatusView.SetText(s)
+}
+
+func gRPCTicker(sv *GRPCStatusView, conn *grpc.ClientConn) {
+	//TODO: refactor -> get rid of hardcoded values
+	ticker := time.NewTicker(5 * time.Second)
+	for range ticker.C {
+		if str := conn.GetState().String(); str == "READY" || str == "IDLE" {
+			sv.SetContent("[green]" + "connected")
+		} else {
+			sv.SetContent("[red]" + "disconnected")
+		}
+	}
+}
diff --git a/cmd/gosdn-tview/views/headerView.go b/cmd/gosdn-tview/views/headerView.go
new file mode 100644
index 0000000000000000000000000000000000000000..67034bb6492f01563321a8cd777323367689685b
--- /dev/null
+++ b/cmd/gosdn-tview/views/headerView.go
@@ -0,0 +1,32 @@
+package views
+
+import "github.com/rivo/tview"
+
+var goSDNAscii = `		 ____  ____  _   _           _   _            _              _           _        ____                           _            _ _
+  __ _  ___/ ___||  _ \| \ | |         | | | | ___   ___| |__  ___  ___| |__  _   _| | ___  |  _ \  __ _ _ __ _ __ ___  ___| |_ __ _  __| | |_
+ / _  |/ _ \___ \| | | |  \| |  _____  | |_| |/ _ \ / __| '_ \/ __|/ __| '_ \| | | | |/ _ \ | | | |/ _  | '__| '_   _ \/ __| __/ _  |/ _  | __|
+| (_| | (_) |__) | |_| | |\  | |_____| |  _  | (_) | (__| | | \__ \ (__| | | | |_| | |  __/ | |_| | (_| | |  | | | | | \__ \ || (_| | (_| | |_
+ \__  |\___/____/|____/|_| \_|         |_| |_|\___/ \___|_| |_|___/\___|_| |_|\__,_|_|\___| |____/ \__,_|_|  |_| |_| |_|___/\__\__,_|\__,_|\__|
+ |___/																																	    `
+
+type HeaderView struct {
+	headerFlex *tview.Flex
+	titleView  *tview.TextView
+}
+
+func NewHeaderView() *HeaderView {
+	//TODO: change to uses FlexBox if there is more to display in the header
+	hv := &HeaderView{
+		titleView: tview.NewTextView(),
+	}
+	hv.titleView.
+		SetText(goSDNAscii).
+		SetTextAlign(tview.AlignCenter).
+		SetBorder(true)
+
+	return hv
+}
+
+func (hv *HeaderView) GetContent() tview.Primitive {
+	return hv.titleView
+}
diff --git a/cmd/gosdn-tview/views/mainView.go b/cmd/gosdn-tview/views/mainView.go
new file mode 100644
index 0000000000000000000000000000000000000000..6c95c811cc408ee1f5e5fa480ba33e573d044555
--- /dev/null
+++ b/cmd/gosdn-tview/views/mainView.go
@@ -0,0 +1,45 @@
+package views
+
+import (
+	"code.fbi.h-da.de/cocsn/gosdn/cmd/gosdn-tview/app"
+	"github.com/rivo/tview"
+	"google.golang.org/grpc"
+)
+
+type MainView struct {
+	pages              *tview.Pages
+	mainGrid           *tview.Grid
+	commandsListView   *CommandListView
+	resultAndInputView *ResultAndInputView
+	headerView         *HeaderView
+	footerView         *FooterView
+}
+
+func NewMainView(app *app.App, conn *grpc.ClientConn) *MainView {
+	mv := &MainView{
+		pages:              tview.NewPages(),
+		mainGrid:           tview.NewGrid(),
+		commandsListView:   NewCommandListView(),
+		resultAndInputView: NewResultAndInputView(app),
+		headerView:         NewHeaderView(),
+		footerView:         NewFooterView(app, conn),
+	}
+	mv.commandsListView.GetCommands(app, mv.resultAndInputView, conn)
+
+	mv.mainGrid.
+		SetRows(8, 0, 5).
+		SetColumns(40, 0).
+		AddItem(mv.headerView.GetContent(), 0, 0, 1, 2, 0, 0, false).
+		AddItem(mv.footerView.GetContent(), 2, 0, 1, 2, 0, 0, false)
+
+	mv.mainGrid.AddItem(mv.commandsListView.GetContent(), 1, 0, 1, 1, 0, 0, true).
+		AddItem(mv.resultAndInputView.GetContent(), 1, 1, 1, 1, 0, 0, false)
+
+	mv.pages.AddPage("main", mv.mainGrid, true, true)
+
+	return mv
+}
+
+func (mv *MainView) GetContent() tview.Primitive {
+	return mv.pages
+}
diff --git a/cmd/gosdn-tview/views/resultAndInputView.go b/cmd/gosdn-tview/views/resultAndInputView.go
new file mode 100644
index 0000000000000000000000000000000000000000..99ae89654349c6347281c34c7b2149a6e4c64463
--- /dev/null
+++ b/cmd/gosdn-tview/views/resultAndInputView.go
@@ -0,0 +1,45 @@
+package views
+
+import (
+	"code.fbi.h-da.de/cocsn/gosdn/cmd/gosdn-tview/app"
+	"github.com/rivo/tview"
+)
+
+type ResultAndInputView struct {
+	pages        *tview.Pages
+	resultView   *tview.TextView
+	pndInputView *AddPNDView
+}
+
+func NewResultAndInputView(app *app.App) *ResultAndInputView {
+	rv := &ResultAndInputView{
+		pages:        tview.NewPages(),
+		pndInputView: NewAddPNDView(app),
+		resultView:   tview.NewTextView(),
+	}
+	rv.resultView.
+		SetDynamicColors(true).
+		SetRegions(true).
+		SetScrollable(true).
+		SetTitle("Result").
+		SetBorder(true)
+
+	rv.pages.
+		AddPage("result", rv.resultView, true, true).
+		AddPage("addPND", rv.pndInputView.GetContent(), true, false)
+
+	return rv
+}
+
+func (rv *ResultAndInputView) GetContent() tview.Primitive {
+	return rv.pages
+}
+
+func (rv *ResultAndInputView) ChangeContentView(s string) {
+	rv.pages.SwitchToPage(s)
+}
+
+func (rv *ResultAndInputView) SetContent(s string) {
+	rv.resultView.Clear()
+	rv.resultView.SetText(s)
+}
diff --git a/configs/gosdn.toml b/configs/gosdn.toml
index 26d755b34702b3733efb841a7d0e3148e4d0a30c..c749257f4e595ddc1c2fbc7bdc1cce06742b3562 100644
--- a/configs/gosdn.toml
+++ b/configs/gosdn.toml
@@ -1,4 +1,7 @@
-#example gosdn.toml
-CliSocket       = "localhost:55055"
-DatabaseSocket  = "bolt://141.100.70.170:7687"
-ConfigPath      = "./configs/gosdn.toml"
+# example config
+CliSocket = "localhost:55055"
+DatabaseSocket = "bolt://141.100.70.170:7687"
+DatabaseUser = ""
+DatabasePassword = ""
+DatabaseCrypto = false
+ConfigPath = "./configs/gosdn.toml"
diff --git a/go.mod b/go.mod
index 6dc61c2bc002bdf283ea14c6fadaa5d7794ae130..b55c84e7746a120ddb95e8d00d1776078cc7b6dc 100644
--- a/go.mod
+++ b/go.mod
@@ -11,8 +11,8 @@ require (
 	github.com/google/go-cmp v0.4.1 // indirect
 	github.com/neo4j/neo4j-go-driver v1.8.3
 	github.com/onsi/ginkgo v1.13.0 // indirect
+	github.com/rivo/tview v0.0.0-20201018122409-d551c850a743
 	golang.org/x/net v0.0.0-20200904194848-62affa334b73 // indirect
-	golang.org/x/sys v0.0.0-20200817155316-9781c653f443 // indirect
 	google.golang.org/genproto v0.0.0-20200519141106-08726f379972 // indirect
 	google.golang.org/grpc v1.29.1
 	google.golang.org/protobuf v1.23.0
diff --git a/go.sum b/go.sum
index aae8fb048e6cffa8b8c77b59b035853f1417ab2c..86322fe5c669de0df7af85a81f4ccdbf4f888403 100644
--- a/go.sum
+++ b/go.sum
@@ -32,6 +32,10 @@ github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV
 github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
 github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
 github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
+github.com/gdamore/encoding v1.0.0 h1:+7OoQ1Bc6eTm5niUzBa0Ctsh6JbMW6Ra+YNuAtDBdko=
+github.com/gdamore/encoding v1.0.0/go.mod h1:alR0ol34c49FCSBLjhosxzcPHQbf2trDkoo5dl+VrEg=
+github.com/gdamore/tcell/v2 v2.0.1-0.20201017141208-acf90d56d591 h1:0WWUDZ1oxq7NxVyGo8M3KI5jbkiwNAdZFFzAdC68up4=
+github.com/gdamore/tcell/v2 v2.0.1-0.20201017141208-acf90d56d591/go.mod h1:vSVL/GV5mCSlPC6thFP5kfOFdM9MGZcalipmpTxTgQA=
 github.com/globalsign/mgo v0.0.0-20180905125535-1ca0a4f7cbcb/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q=
 github.com/globalsign/mgo v0.0.0-20181015135952-eeefdecb41b8/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q=
 github.com/go-openapi/analysis v0.0.0-20180825180245-b006789cd277/go.mod h1:k70tL6pCuVxPJOHXQ+wIac1FUrvNkHolPie/cLEU6hI=
@@ -171,6 +175,8 @@ github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA=
 github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
 github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
 github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
+github.com/lucasb-eyer/go-colorful v1.0.3 h1:QIbQXiugsb+q10B+MI+7DI1oQLdmnep86tWFlaaUAac=
+github.com/lucasb-eyer/go-colorful v1.0.3/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
 github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
 github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
 github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
@@ -179,6 +185,9 @@ github.com/mailru/easyjson v0.7.1 h1:mdxE1MF9o53iCb2Ghj1VfWvh7ZOwHpnVG/xwXrV90U8
 github.com/mailru/easyjson v0.7.1/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs=
 github.com/markbates/oncer v0.0.0-20181203154359-bf2de49a0be2/go.mod h1:Ld9puTsIW75CHf65OeIOkyKbteujpZVXDpWK6YGZbxE=
 github.com/markbates/safe v1.0.1/go.mod h1:nAqgmRi7cY2nqMc92/bSEeQA+R4OheNU2T1kNSCBdG0=
+github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
+github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0=
+github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
 github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
 github.com/mitchellh/mapstructure v1.3.2 h1:mRS76wmkOn3KkKAyXDu42V+6ebnXWIztFSYGN7GeoRg=
 github.com/mitchellh/mapstructure v1.3.2/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
@@ -208,6 +217,10 @@ github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE
 github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
 github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
 github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
+github.com/rivo/tview v0.0.0-20201018122409-d551c850a743 h1:9BBjVJTRxuYBeCAv9DFH2hSzY0ujLx5sxMg5D3K/Xeg=
+github.com/rivo/tview v0.0.0-20201018122409-d551c850a743/go.mod h1:t7mcA3nlK9dxD1DMoz/DQRMWFMkGBUj6rJBM5VNfLFA=
+github.com/rivo/uniseg v0.1.0 h1:+2KBaVoUmb9XzDsrx/Ct0W/EYOSFf/nWTauy++DprtY=
+github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
 github.com/rogpeppe/go-internal v1.1.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
 github.com/rogpeppe/go-internal v1.2.2/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
 github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
@@ -282,18 +295,21 @@ golang.org/x/sys v0.0.0-20190419153524-e8e3143a4f4a/go.mod h1:h1NjWce9XRLGQEsW7w
 golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20190531175056-4c3a928424d2/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190626150813-e07cf5db2756/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200817155316-9781c653f443 h1:X18bCaipMcoJGm27Nv7zr4XYPKGUy92GtqboKC2Hxaw=
-golang.org/x/sys v0.0.0-20200817155316-9781c653f443/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20201017003518-b09fb700fbb7 h1:XtNJkfEjb4zR3q20BBBcYUykVOEMgZeIUOpBPfNYgxg=
+golang.org/x/sys v0.0.0-20201017003518-b09fb700fbb7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
 golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
+golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k=
+golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
 golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
 golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
 golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=