diff --git a/include/memory_space.h b/include/memory_space.h
index f9a3d2b06e7c13b66768e5fbc1274f2aea69cb4f..fa263b9f67936c6d2ca5a02c55ab0263c8259ca1 100644
--- a/include/memory_space.h
+++ b/include/memory_space.h
@@ -34,7 +34,6 @@
 
 namespace Zipr_SDK
 {
-class Options_t;
 
 typedef std::set<Range_t, Range_tCompare> RangeSet_t;
 
diff --git a/include/zipr_options.h b/include/zipr_options.h
index d94048fb96c44b213f58704310a7def2caa2d5ea..6396f70419ec28b2de5a54fff1ed8a820fd409c4 100644
--- a/include/zipr_options.h
+++ b/include/zipr_options.h
@@ -28,27 +28,255 @@
  * E-mail: jwd@zephyr-software.com
  **************************************************************************/
 
-#ifndef zipr_sdk_zipr_options_h
-#define zipr_sdk_zipr_options_h
+#ifndef zipr_sdk_zipr_plugin_options_h
+#define zipr_sdk_zipr_plugin_options_h
 
 #include <string>
 #include <unistd.h>
 #include <libIRDB-core.hpp>
+#include <iostream>
 
 namespace Zipr_SDK
 {
 
+class ZiprUntypedOption_t 
+{
+	public:
+		ZiprUntypedOption_t()
+			: m_key(""),
+			  m_untyped_value(""),
+				m_takes_value(true),
+				m_needs_value(true),
+				m_required(false),
+				m_set(false) {};
+		ZiprUntypedOption_t(std::string key, std::string value)
+			: m_key(key),
+			  m_untyped_value(value),
+				m_takes_value(true),
+				m_needs_value(true),
+				m_required(false),
+				m_set(false) {};
+
+		virtual void SetValue(const std::string &value) = 0;
+		virtual void Set() = 0;
+
+		std::string StringValue() {
+			return m_untyped_value;
+		}
+		std::string Namespace() {
+			return m_namespace;
+		}
+		std::string Key() {
+			return m_key;
+		}
+		void SetNeedsValue(bool needs_value) {
+			m_needs_value = needs_value;
+		}
+		bool NeedsValue() {
+			return m_needs_value;
+		}
+		void SetTakesValue(bool takes_value) {
+			m_takes_value = takes_value;
+		}
+		bool TakesValue() {
+			return m_takes_value;
+		}
+		
+		bool Required() {
+			return m_required;
+		}
+		void SetRequired(bool required) {
+			m_required = required;
+		}
+		bool RequirementMet() {
+			return (!m_required) || (m_set);
+		}
+
+		virtual std::string Description() {
+			return m_description;
+		}
+		void SetDescription(std::string description) {
+			m_description = description;
+		}
+
+		void AddObserver(ZiprUntypedOption_t *observer) {
+			observer->SetValue(m_untyped_value);
+			m_observers.insert(observer);
+		}
+	protected:
+		std::string m_namespace, m_key, m_untyped_value, m_description;
+		std::set<ZiprUntypedOption_t*> m_observers;
+		bool m_takes_value, m_needs_value;
+		bool m_required;
+		bool m_set;
+		void SetObserverValues(std::string value) {
+			std::set<ZiprUntypedOption_t*>::const_iterator it = m_observers.begin();
+			std::set<ZiprUntypedOption_t*>::const_iterator it_end = m_observers.end();
+			for (; it!=it_end; it++)
+				(*it)->SetValue(value);
+		}
+};
 
-class Options_t 
+template <typename T>
+class ZiprTypedOption_t : public ZiprUntypedOption_t
 {
 	public:
-		virtual std::string GetOutputFileName(libIRDB::File_t* p_file)=0;
-		virtual std::string GetCallbackFileName()=0;
-		virtual int GetVariantID()=0;
-		virtual int GetVerbose()=0;
-		virtual int GetArchitecture()=0;
-		virtual std::string GetObjcopyPath() =0;
+		using ZiprUntypedOption_t::ZiprUntypedOption_t;
+		void SetValue(const std::string &value) {
+			m_set = true;
+			m_untyped_value = value;
+			m_value = ConvertToTyped(value);
+			SetObserverValues(value);
+		}
+		virtual void Set() {
+		}
 
+		T Value() const {
+			return m_value;
+		}
+		operator T() const { return Value(); };
+		bool operator==(const T &r) {
+			return Value() == r;
+		}
+		std::string Description() final {
+			return std::string(m_key + ": \t" 
+			+ m_description + " ("
+			+ TypeName() + ", "
+			+ ((!m_required)?"not ":"") + "required)");
+		}
+	protected:
+		T m_value;
+		virtual T ConvertToTyped(std::string) = 0;
+		virtual std::string ConvertToUntyped(T) = 0;
+		virtual std::string TypeName() = 0;
+};
+
+class ZiprStringOption_t : public ZiprTypedOption_t<std::string>
+{
+	public:
+		using ZiprTypedOption_t<std::string>::ZiprTypedOption_t;
+		ZiprStringOption_t(std::string key, std::string value = "")
+			: ZiprTypedOption_t(key, value) {
+			m_value = ConvertToTyped(value);
+		}
+	protected:
+		std::string ConvertToTyped(std::string value_to_convert) {
+			return std::string(value_to_convert);
+		}
+		std::string ConvertToUntyped(std::string value_to_convert) {
+			return std::string(value_to_convert);
+		}
+		std::string TypeName() {
+			return "string";
+		}
+};
+
+class ZiprBooleanOption_t : public ZiprTypedOption_t<bool>
+{
+	public:
+		ZiprBooleanOption_t(std::string key, std::string value = "") {
+			m_key = key;
+			m_untyped_value = value;
+			m_needs_value = false;
+		}
+		ZiprBooleanOption_t(std::string key, bool value)
+			: ZiprBooleanOption_t(key) {
+			m_value = value;
+			m_untyped_value = ConvertToUntyped(value);
+		}
+		void Set() {
+			m_untyped_value = "true";
+			m_value = true;
+			m_set = true;
+			SetObserverValues(m_untyped_value);
+		}
+
+	private:
+		bool ConvertToTyped(std::string value_to_convert) {
+			if (value_to_convert == "true")
+				return true;
+			else
+				return false;
+		}
+		std::string ConvertToUntyped(bool value_to_convert) {
+			return (value_to_convert ? std::string("true") : std::string("false"));
+		}
+		std::string TypeName() {
+			return "bool";
+		}
+};
+
+class ZiprIntegerOption_t : public ZiprTypedOption_t<int>
+{
+	public:
+		using ZiprTypedOption_t<int>::ZiprTypedOption_t;
+		ZiprIntegerOption_t(std::string key, std::string value = "")
+			: ZiprTypedOption_t(key, value) {
+			m_value = ConvertToTyped(value);
+		}
+		ZiprIntegerOption_t(std::string key, int value)
+			: ZiprTypedOption_t(key, "") {
+			m_value = value;
+			m_untyped_value = ConvertToUntyped(value);
+		}
+		void SetValue(int value) {
+			std::set<ZiprUntypedOption_t*>::const_iterator it = m_observers.begin();
+			std::set<ZiprUntypedOption_t*>::const_iterator it_end = m_observers.end();
+			m_value = value;
+			m_untyped_value = ConvertToUntyped(value);
+			SetObserverValues(m_untyped_value);
+		}
+	private:
+		int ConvertToTyped(std::string value_to_convert) {
+			try {
+				return std::stoi(value_to_convert);
+			} catch (std::exception &e) {
+				m_set = false;
+				m_untyped_value = "";
+				return 0;
+			}
+		}
+		std::string ConvertToUntyped(int value_to_convert) {
+			try {
+				return std::to_string(value_to_convert);
+			} catch (std::exception &e) {
+				return std::string("");
+			}
+		}
+		std::string TypeName() {
+			return "integer";
+		}
+};
+
+class ZiprOptionsNamespace_t : public std::set<ZiprUntypedOption_t*>
+{
+	public:
+		ZiprOptionsNamespace_t(std::string ns) : m_namespace(ns) {}
+		std::string Namespace() {
+			return m_namespace;
+		};
+		void PrintNamespace();
+		ZiprUntypedOption_t *OptionByKey(std::string key);
+		void AddOption(ZiprUntypedOption_t *option);
+		void PrintUsage(int tabs, std::ostream &out);
+		bool RequirementsMet();
+		void MergeNamespace(ZiprOptionsNamespace_t*);
+	private:
+		std::string m_namespace;
+};
+
+class ZiprOptions_t {
+	public:
+		ZiprOptions_t(int argc, char **argv);
+		void AddNamespace(ZiprOptionsNamespace_t *);
+		void PrintNamespaces();
+		bool Parse(std::ostream &error = std::cout, std::ostream &warn = std::cerr);
+		ZiprOptionsNamespace_t *Namespace(std::string);
+		void PrintUsage(std::ostream &out);
+		bool RequirementsMet();
+	private:
+		std::vector<std::string> m_arguments;
+		std::set<ZiprOptionsNamespace_t*> m_namespaces;
 };
 
 }
diff --git a/include/zipr_plugin.h b/include/zipr_plugin.h
index 19ee473bff2ebafa2cde91bf762a56b1ec4d4949..935f85c79a37221ea21175729dca7e3d1a4d1732 100644
--- a/include/zipr_plugin.h
+++ b/include/zipr_plugin.h
@@ -40,11 +40,14 @@ class ZiprPluginInterface_t
 		{
 			return 0;
 		}
-
 		virtual std::string ToString()
 		{
 			return "NamelessPlugin";
 		}
+		virtual ZiprOptionsNamespace_t *RegisterOptions(ZiprOptionsNamespace_t *)
+		{
+			return new ZiprOptionsNamespace_t("");
+		}
 };
 
 }