diff --git a/Cargo.lock b/Cargo.lock
index e25d153..4127545 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -129,6 +129,7 @@ version = "0.1.0"
 dependencies = [
  "abi_stable",
  "anyrun-interface",
+ "anyrun-macros",
  "clap",
  "gtk",
  "gtk-layer-shell",
@@ -145,21 +146,21 @@ dependencies = [
  "abi_stable",
 ]
 
+[[package]]
+name = "anyrun-macros"
+version = "0.1.0"
+dependencies = [
+ "quote",
+ "syn 2.0.15",
+]
+
 [[package]]
 name = "anyrun-plugin"
 version = "0.1.0"
 dependencies = [
  "abi_stable",
  "anyrun-interface",
- "anyrun-plugin-macros",
-]
-
-[[package]]
-name = "anyrun-plugin-macros"
-version = "0.1.0"
-dependencies = [
- "quote",
- "syn 2.0.15",
+ "anyrun-macros",
 ]
 
 [[package]]
diff --git a/Cargo.toml b/Cargo.toml
index ea9d9eb..2ac6b5d 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -2,7 +2,7 @@
 members = [
   "anyrun",
   "anyrun-plugin",
-  "anyrun-plugin-macros",
+  "anyrun-macros",
   "anyrun-interface",
   "plugins/applications",
   "plugins/symbols",
diff --git a/README.md b/README.md
index 358b52e..e13c323 100644
--- a/README.md
+++ b/README.md
@@ -167,7 +167,10 @@ Anyrun supports [GTK+ CSS](https://docs.gtk.org/gtk3/css-overview.html) styling.
 The custom arguments for anyrun are as follows:
 
 - `--config-dir`, `-c`: Override the configuration directory
-- `--override-plugins`, `-o`: Override the plugins to be used, provided in the same way as in the config file.
+
+The rest of the arguments are automatically generated based on the config, and can be used to override
+configuration parameters. For example if you want to temporarily only run the Applications and Symbols plugins on
+the top side of the screen, you would run `anyrun --plugins libapplications.so --plugins libsymbols.so --position top`.
 
 # Plugin development
 
diff --git a/anyrun-plugin-macros/Cargo.toml b/anyrun-macros/Cargo.toml
similarity index 89%
rename from anyrun-plugin-macros/Cargo.toml
rename to anyrun-macros/Cargo.toml
index e5706b1..73ac987 100644
--- a/anyrun-plugin-macros/Cargo.toml
+++ b/anyrun-macros/Cargo.toml
@@ -1,5 +1,5 @@
 [package]
-name = "anyrun-plugin-macros"
+name = "anyrun-macros"
 version = "0.1.0"
 edition = "2021"
 
diff --git a/anyrun-plugin-macros/src/lib.rs b/anyrun-macros/src/lib.rs
similarity index 86%
rename from anyrun-plugin-macros/src/lib.rs
rename to anyrun-macros/src/lib.rs
index a0ef535..7678375 100644
--- a/anyrun-plugin-macros/src/lib.rs
+++ b/anyrun-macros/src/lib.rs
@@ -1,6 +1,6 @@
-use proc_macro::TokenStream;
+use proc_macro::{Span, TokenStream};
 use quote::quote;
-use syn::{parse_macro_input, ReturnType, Type};
+use syn::{parse_macro_input, parse_quote, Attribute, Ident, ReturnType, Type};
 
 /// The function to handle the selection of an item. Takes a `Match` as its first argument, and the second argument can be one of:
 /// - &T
@@ -208,3 +208,45 @@ pub fn init(_attr: TokenStream, item: TokenStream) -> TokenStream {
     }
     .into()
 }
+
+#[proc_macro_attribute]
+pub fn config_args(_attr: TokenStream, item: TokenStream) -> TokenStream {
+    let item = parse_macro_input!(item as syn::ItemStruct);
+    let ident = &item.ident;
+
+    let mut opt_item = item.clone();
+
+    opt_item.attrs = vec![parse_quote!(#[derive(::clap::Args)])];
+    opt_item.ident = Ident::new(&format!("{}Args", opt_item.ident), Span::call_site().into());
+
+    let opt_ident = &opt_item.ident;
+
+    let mut operations = quote!();
+
+    for field in opt_item.fields.iter_mut() {
+        let ty = &field.ty;
+        let ident = &field.ident;
+        field.ty = Type::Verbatim(quote!(Option<#ty>));
+        field.attrs = vec![parse_quote!(#[arg(long)])];
+
+        operations = quote! {
+            #operations
+            if let Some(val) = opt.#ident {
+                self.#ident = val;
+            }
+        }
+    }
+
+    quote! {
+        #item
+
+        #opt_item
+
+        impl #ident {
+            fn merge_opt(&mut self, opt: #opt_ident) {
+                #operations
+            }
+        }
+    }
+    .into()
+}
diff --git a/anyrun-plugin/Cargo.toml b/anyrun-plugin/Cargo.toml
index 5266059..aa2866b 100644
--- a/anyrun-plugin/Cargo.toml
+++ b/anyrun-plugin/Cargo.toml
@@ -8,4 +8,4 @@ edition = "2021"
 [dependencies]
 abi_stable = "0.11.1"
 anyrun-interface = { path = "../anyrun-interface" }
-anyrun-plugin-macros = { path = "../anyrun-plugin-macros" }
+anyrun-macros = { path = "../anyrun-macros" }
diff --git a/anyrun-plugin/src/lib.rs b/anyrun-plugin/src/lib.rs
index 9b496bf..c5d7cc8 100644
--- a/anyrun-plugin/src/lib.rs
+++ b/anyrun-plugin/src/lib.rs
@@ -6,7 +6,7 @@ on what each of these should be is found in their respective attribute macros.
 !*/
 
 pub use anyrun_interface::{self, HandleResult, Match, PluginInfo};
-pub use anyrun_plugin_macros::*;
+pub use anyrun_macros::{get_matches, handler, info, init};
 
 /*
 The macro to create a plugin, handles asynchronous execution of getting the matches and the boilerplate
diff --git a/anyrun/Cargo.toml b/anyrun/Cargo.toml
index c4918ca..373e380 100644
--- a/anyrun/Cargo.toml
+++ b/anyrun/Cargo.toml
@@ -6,6 +6,7 @@ edition = "2021"
 # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
 
 [dependencies]
+anyrun-macros = { path = "../anyrun-macros" }
 abi_stable = "0.11.1"
 gtk = "0.16.2"
 gtk-layer-shell = { version = "0.5.0", features = ["v0_6"] }
diff --git a/anyrun/src/main.rs b/anyrun/src/main.rs
index eb0ef41..04f044f 100644
--- a/anyrun/src/main.rs
+++ b/anyrun/src/main.rs
@@ -11,12 +11,13 @@ use std::{
 
 use abi_stable::std_types::{ROption, RVec};
 use anyrun_interface::{HandleResult, Match, PluginInfo, PluginRef, PollResult};
-use clap::Parser;
+use clap::{Parser, ValueEnum};
 use gtk::{gdk, gdk_pixbuf, gio, glib, prelude::*};
 use nix::unistd;
 use serde::Deserialize;
 use wl_clipboard_rs::copy;
 
+#[anyrun_macros::config_args]
 #[derive(Deserialize)]
 struct Config {
     width: RelativeNum,
@@ -55,7 +56,7 @@ impl Default for Config {
     }
 }
 
-#[derive(Deserialize)]
+#[derive(Deserialize, Clone, ValueEnum)]
 enum Layer {
     Background,
     Bottom,
@@ -64,12 +65,24 @@ enum Layer {
 }
 
 // Could have a better name
-#[derive(Deserialize)]
+#[derive(Deserialize, Clone)]
 enum RelativeNum {
     Absolute(i32),
     Fraction(f32),
 }
 
+impl From<&str> for RelativeNum {
+    fn from(value: &str) -> Self {
+        let (ty, val) = value.split_once(':').expect("Invalid RelativeNum value");
+
+        match ty {
+            "absolute" => Self::Absolute(val.parse().unwrap()),
+            "fraction" => Self::Fraction(val.parse().unwrap()),
+            _ => panic!("Invalid type of value"),
+        }
+    }
+}
+
 /// A "view" of plugin's info and matches
 #[derive(Clone)]
 struct PluginView {
@@ -83,12 +96,11 @@ struct Args {
     /// Override the path to the config directory
     #[arg(short, long)]
     config_dir: Option<String>,
-    /// Override plugin selection
-    #[arg(short, long, value_delimiter = ' ', num_args = 1..)]
-    override_plugins: Option<Vec<PathBuf>>,
+    #[command(flatten)]
+    config: ConfigArgs,
 }
 
-#[derive(Deserialize)]
+#[derive(Deserialize, Clone, ValueEnum)]
 enum Position {
     Top,
     Center,
@@ -183,9 +195,7 @@ fn main() {
         ),
     };
 
-    if let Some(override_plugins) = args.override_plugins {
-        config.plugins = override_plugins;
-    }
+    config.merge_opt(args.config);
 
     let runtime_data: Rc<RefCell<RuntimeData>> = Rc::new(RefCell::new(RuntimeData {
         exclusive: None,