diff --git a/applications/gui2/src/views/addsource.cpp b/applications/gui2/src/views/addsource.cpp
index 91b9041aec3f356ebe226873454b004f8c446725..0fe514d7d3fceff0ecf7dbaabe11716310f146df 100644
--- a/applications/gui2/src/views/addsource.cpp
+++ b/applications/gui2/src/views/addsource.cpp
@@ -8,6 +8,7 @@
 #include <nanogui/button.h>
 #include <nanogui/vscrollpanel.h>
 #include <nanogui/tabwidget.h>
+#include <nanogui/formhelper.h>
 
 #include <loguru.hpp>
 
@@ -168,13 +169,38 @@ void AddSourceWindow::rebuild() {
 		_addButton(s, tab_items_[2]);
 	}
 
-	button = new Button(tab_items_[3], "Add Host", ENTYPO_ICON_PLUS);
-	button->setIconPosition(Button::IconPosition::Left);
-	button->setIconExtraScale(1.2);
+	auto *host_menu = new Widget(tab_items_[3]);
+	host_menu->setLayout(new BoxLayout(nanogui::Orientation::Horizontal, nanogui::Alignment::Maximum, 5,4));
+
+	button = new Button(host_menu, "Add", ENTYPO_ICON_PLUS);
 	button->setFontSize(18);
-	button->setTooltip("Manually add a new connection URI");
+	button->setTooltip("Connect to a new machine");
 	button->setCallback([this]() {
+		FormHelper *fh = new FormHelper(screen());
+		auto *win = fh->addWindow(Vector2i(10,10), "Add Host");
+		win->center();
+		win->setTheme(dynamic_cast<ftl::gui2::Screen*>(win->screen())->getTheme("window_dark"));
+		//win->setWidth(200);
+		fh->addVariable<std::string>("URI", [this,win](const std::string &v) {
+			try {
+				ctrl_->add(v);
+			} catch (const ftl::exception &e) {
+				LOG(ERROR) << "Add failed: " << e.what();
+			}
+			win->dispose();
+		}, [this]() {
+			return "";
+		})->setFixedWidth(150);
+		win->screen()->performLayout();
+		delete fh;
+	});
 
+	button = new Button(host_menu, "Clear", ENTYPO_ICON_CYCLE);
+	button->setFontSize(18);
+	button->setTooltip("Clear host history");
+	button->setCallback([this]() {
+		ctrl_->feed()->clearHostHistory();
+		uptodate_.clear();
 	});
 
 	auto hostsrcs = ctrl_->getHosts();
@@ -239,9 +265,7 @@ void AddSourceWindow::draw(NVGcontext *ctx) {
 	{
 		UNIQUE_LOCK(mutex_, lk);
 		if (!uptodate_.test_and_set()) {
-			tabs_->requestFocus();
-			// Note the 1, first widget is the title bar buttons
-			//while(childCount() > 1) { removeChild(childCount()-1); }
+			tabs_->requestFocus();  // Must ensure focus item not deleted
 			rebuild();
 			screen()->performLayout();
 		}
diff --git a/components/streams/include/ftl/streams/feed.hpp b/components/streams/include/ftl/streams/feed.hpp
index 5cfddc7071acd25c2795bebe0f8bf8a62d573640..c113d6fcfb5bf87de8ac3bcfd70e382f007aa540 100644
--- a/components/streams/include/ftl/streams/feed.hpp
+++ b/components/streams/include/ftl/streams/feed.hpp
@@ -112,6 +112,7 @@ public:
 	bool sourceActive(const std::string &uri);
 
 	void clearFileHistory();
+	void clearHostHistory();
 
 	/**
 	 * Perform a render tick for all render sources. Note that this must be
diff --git a/components/streams/src/feed.cpp b/components/streams/src/feed.cpp
index 6d149d13189b48a55d0868127154db9c713862da..81f6881b99b649fd15e8b999f12f36505426090e 100644
--- a/components/streams/src/feed.cpp
+++ b/components/streams/src/feed.cpp
@@ -595,6 +595,22 @@ std::vector<std::string> Feed::knownHosts() {
 	return hosts;
 }
 
+void Feed::clearHostHistory() {
+	UNIQUE_LOCK(mtx_, lk);
+	auto &known = getConfig()["known_hosts"];
+	known.clear();
+
+	auto &recent = getConfig()["recent_sources"];
+	for (auto i=recent.begin(); i != recent.end();) {
+		ftl::URI uri(i.key());
+		if (uri.getScheme() == ftl::URI::SCHEME_TCP || uri.getScheme() == ftl::URI::SCHEME_WS) {
+			i = recent.erase(i);
+		} else {
+			++i;
+		}
+	}
+}
+
 std::set<ftl::stream::SourceInfo> Feed::recentSources() {
 	std::set<ftl::stream::SourceInfo> result;
 
@@ -873,7 +889,7 @@ uint32_t Feed::add(const std::string &path) {
 		auto &host_details = known_hosts[uri.getBaseURIWithUser()];
 		host_details["last_open"] = ftl::timer::get_time();
 
-		ftl::pool.push([this,path](int id) { net_->connect(path); });
+		ftl::pool.push([this,path](int id) { net_->connect(path)->noReconnect(); });
 
 	}
 	else if (scheme == ftl::URI::SCHEME_FTL) {