diff --git a/applications/gui/src/main.cpp b/applications/gui/src/main.cpp
index 7875e52bb04afc59953ac1a728dafe64008b6d6c..5ebc552fa0ee0664c7a0b7898a723b90bf87f29c 100644
--- a/applications/gui/src/main.cpp
+++ b/applications/gui/src/main.cpp
@@ -25,10 +25,12 @@ int main(int argc, char **argv) {
 
 	std::map<ftl::UUID, std::vector<ftl::NetConfigurable*>> peerConfigurables;
 
+	// FIXME: Move this elsewhere, it is not just for GUI
 	net->onConnect([&controller, &peerConfigurables](ftl::net::Peer *p) {
 		ftl::UUID peer = p->id();
 		auto cs = controller->getConfigurables(peer);
 		for (auto c : cs) {
+			//LOG(INFO) << "NET CONFIG: " << c;
 			ftl::config::json_t *configuration = new ftl::config::json_t;
 			*configuration = controller->get(peer, c);
 			if (!configuration->empty()) {
diff --git a/applications/gui/src/screen.cpp b/applications/gui/src/screen.cpp
index 811d96cf851781add465e4ec58ee97e93e5c98f2..76665281fc1b9fcbb1b0b45609c509d02f88a69d 100644
--- a/applications/gui/src/screen.cpp
+++ b/applications/gui/src/screen.cpp
@@ -84,6 +84,8 @@ ftl::gui::Screen::Screen(ftl::Configurable *proot, ftl::net::Universe *pnet, ftl
 		pos_y_ = root_->value("position_y", 0.0f);
 	});
 
+	shortcuts_ = ftl::create<ftl::Configurable>(root_, "shortcuts");
+
 	setSize(Vector2i(1280,720));
 
 	toolbuttheme = new Theme(*theme());
@@ -434,12 +436,31 @@ bool ftl::gui::Screen::mouseButtonEvent(const nanogui::Vector2i &p, int button,
 	}
 }
 
+static std::string generateKeyComboStr(int key, int modifiers) {
+	std::string res = "";
+
+	switch(modifiers) {
+	case 1:		res += "Shift+"; break;
+	case 2:		res += "Ctrl+"; break;
+	case 3:		res += "Ctrl+Shift+"; break;
+	case 4:		res += "Alt+"; break;
+	default: break;
+	}
+
+	if (key < 127 && key >= 32) {
+		char buf[2] = { (char)key, 0 };
+		return res + std::string(buf);
+	} else {
+		return "";
+	}
+}
+
 bool ftl::gui::Screen::keyboardEvent(int key, int scancode, int action, int modifiers) {
 	using namespace Eigen;
 	if (nanogui::Screen::keyboardEvent(key, scancode, action, modifiers)) {
 		return true;
 	} else {
-		LOG(INFO) << "Key press " << key << " - " << action << " - " << modifiers;
+		//LOG(INFO) << "Key press " << key << " - " << action << " - " << modifiers;
 
 		if (key >= 262 && key <= 267) {
 			if (camera_) camera_->keyMovement(key, modifiers);
@@ -447,9 +468,42 @@ bool ftl::gui::Screen::keyboardEvent(int key, int scancode, int action, int modi
 		} else if (action == 1 && key == 'H') {
 			swindow_->setVisible(false);
 			cwindow_->setVisible(false);
-		} else if (action == 1 && key == 32) {
-			ctrl_->pause();
-			return true;
+		} else if (action == 1) {
+			std::string combo = generateKeyComboStr(key, modifiers);
+
+			if (combo.size() > 0) {
+				LOG(INFO) << "Key combo = " << combo;
+
+				auto s = shortcuts_->get<nlohmann::json>(combo);
+				if (s) {
+					//LOG(INFO) << "FOUND KEYBOARD SHORTCUT";
+					std::string op = (*s).value("op",std::string("="));
+					std::string uri = (*s).value("uri",std::string(""));
+
+					if (op == "toggle") {
+						auto v = ftl::config::get(uri);
+						if (v.is_boolean()) {
+							ftl::config::update(uri, !v.get<bool>());
+						}
+					} else if (op == "+=") {
+						auto v = ftl::config::get(uri);
+						if (v.is_number_float()) {
+							ftl::config::update(uri, v.get<float>() + (*s).value("value",0.0f));
+						} else if (v.is_number_integer()) {
+							ftl::config::update(uri, v.get<int>() + (*s).value("value",0));
+						}
+					} else if (op == "-=") {
+						auto v = ftl::config::get(uri);
+						if (v.is_number_float()) {
+							ftl::config::update(uri, v.get<float>() - (*s).value("value",0.0f));
+						} else if (v.is_number_integer()) {
+							ftl::config::update(uri, v.get<int>() - (*s).value("value",0));
+						}
+					} else if (op == "=") {
+						ftl::config::update(uri, (*s)["value"]);
+					}
+				}
+			}
 		}
 		return false;
 	}
diff --git a/applications/gui/src/screen.hpp b/applications/gui/src/screen.hpp
index 9dbed7ead2c064394e1eb877a6a9043ed5b364b4..90cd519bb3681126f4dc4f0d258e342953562433 100644
--- a/applications/gui/src/screen.hpp
+++ b/applications/gui/src/screen.hpp
@@ -101,6 +101,8 @@ class Screen : public nanogui::Screen {
 
 	bool show_two_images_ = false;
 
+	ftl::Configurable *shortcuts_;
+
 	#ifdef HAVE_OPENVR
 	vr::IVRSystem *HMD_;
 	#endif
diff --git a/applications/reconstruct/src/main.cpp b/applications/reconstruct/src/main.cpp
index 551a2dfe309bf8a5a29c17cc4856acb48f70f09c..0dd0a51912e10157a44ea26d793d8364dd60a441 100644
--- a/applications/reconstruct/src/main.cpp
+++ b/applications/reconstruct/src/main.cpp
@@ -241,7 +241,7 @@ static void run(ftl::Configurable *root) {
 	//ftl::voxhash::SceneRep *scene = ftl::create<ftl::voxhash::SceneRep>(root, "voxelhash");
 	ftl::rgbd::Streamer *stream = ftl::create<ftl::rgbd::Streamer>(root, "stream", net);
 	ftl::rgbd::VirtualSource *virt = ftl::create<ftl::rgbd::VirtualSource>(root, "virtual");
-	root->set("tags", nlohmann::json::array({ root->getID()+"/virtual" }));
+	//root->set("tags", nlohmann::json::array({ root->getID()+"/virtual" }));
 	ftl::render::Triangular *splat = ftl::create<ftl::render::Triangular>(root, "renderer", &scene_B);
 	ftl::rgbd::Group *group = new ftl::rgbd::Group;
 	ftl::ILW *align = ftl::create<ftl::ILW>(root, "merge");
diff --git a/components/common/cpp/include/ftl/configuration.hpp b/components/common/cpp/include/ftl/configuration.hpp
index 9e4ba8aed4bcf8b5f2c8cec2c1079edb945359c3..18aaf89f9433911dd71ec3d3519ff2125317e78e 100644
--- a/components/common/cpp/include/ftl/configuration.hpp
+++ b/components/common/cpp/include/ftl/configuration.hpp
@@ -47,6 +47,8 @@ void removeConfigurable(Configurable *cfg);
  */
 bool update(const std::string &puri, const json_t &value);
 
+json_t &get(const std::string &puri);
+
 /**
  * Resolve a JSON schema reference, but do not wait for a remote reference
  * if it is not available. A null entity is returned if not resolved.
diff --git a/components/common/cpp/src/configuration.cpp b/components/common/cpp/src/configuration.cpp
index aa236c8a06772e71d59edd3886ce7a9cb14e2eec..aea0f1b209019332334a8530594d6ba1a84e4587 100644
--- a/components/common/cpp/src/configuration.cpp
+++ b/components/common/cpp/src/configuration.cpp
@@ -194,6 +194,7 @@ ftl::Configurable *ftl::config::find(const std::string &uri) {
 			actual_uri = rootCFG->getID() + uri;
 		}
 	}
+	
 	auto ix = config_instance.find(actual_uri);
 	if (ix == config_instance.end()) return nullptr;
 	else return (*ix).second;
@@ -228,6 +229,7 @@ void ftl::config::registerConfigurable(ftl::Configurable *cfg) {
 		auto tags = cfg->get<vector<string>>("tags");
 		if (tags) {
 			for (auto &t : *tags) {
+				//LOG(INFO) << "REGISTER TAG: " << t;
 				tag_index[t].push_back(cfg);
 			}
 		}
@@ -236,22 +238,47 @@ void ftl::config::registerConfigurable(ftl::Configurable *cfg) {
 
 json_t null_json;
 
+/* To allow for custom tag format */
+static std::string preprocessURI(const std::string &uri) {
+	if (uri[0] == '[') {
+		size_t closing = uri.find_last_of(']');
+		string tags = uri.substr(1, closing-1);
+
+		// TODO: Allow for multiple tags
+
+		const auto &cfgs = ftl::config::findByTag(tags);
+
+		// FIXME: Check for more than one tag result
+		if (cfgs.size() > 0) {
+			//LOG(INFO) << "PREPROC URI " << cfgs[0]->getID() + uri.substr(closing+1);
+			return cfgs[0]->getID() + uri.substr(closing+1);
+		} else {
+			return uri;
+		}
+	} else if (uri[0] == '/') {
+		return rootCFG->getID() + uri;
+	} else {
+		return uri;
+	}
+}
+
 bool ftl::config::update(const std::string &puri, const json_t &value) {
 	// Remove last component of URI
 	string tail = "";
 	string head = "";
-	size_t last_hash = puri.find_last_of('#');
+	string uri = preprocessURI(puri);
+	size_t last_hash = uri.find_last_of('#');
 	if (last_hash != string::npos) {
-		size_t last = puri.find_last_of('/');
+		size_t last = uri.find_last_of('/');
 		if (last != string::npos && last > last_hash) {
-			tail = puri.substr(last+1);
-			head = puri.substr(0, last);
+			tail = uri.substr(last+1);
+			head = uri.substr(0, last);
 		} else {
-			tail = puri.substr(last_hash+1);
-			head = puri.substr(0, last_hash);
+			tail = uri.substr(last_hash+1);
+			head = uri.substr(0, last_hash);
 		}
 	} else {
-		LOG(WARNING) << "Expected a # in an update URI: " << puri;
+		LOG(WARNING) << "Expected a # in an update URI: " << uri;
 		return false;
 	}
 
@@ -284,6 +311,35 @@ bool ftl::config::update(const std::string &puri, const json_t &value) {
 	}
 }
 
+json_t &ftl::config::get(const std::string &puri) {
+	// Remove last component of URI
+	string tail = "";
+	string head = "";
+	string uri = preprocessURI(puri);
+	size_t last_hash = uri.find_last_of('#');
+	if (last_hash != string::npos) {
+		size_t last = uri.find_last_of('/');
+		if (last != string::npos && last > last_hash) {
+			tail = uri.substr(last+1);
+			head = uri.substr(0, last);
+		} else {
+			tail = uri.substr(last_hash+1);
+			head = uri.substr(0, last_hash);
+		}
+	} else {
+		LOG(WARNING) << "Expected a # in an update URI: " << uri;
+		return null_json;
+	}
+
+	Configurable *cfg = find(head);
+
+	if (cfg) {
+		return cfg->getConfig()[tail];
+	} else {
+		return null_json;
+	}
+}
+
 json_t &ftl::config::resolve(const std::string &puri, bool eager) {
 	string uri_str = puri;