diff --git a/Cargo.toml b/Cargo.toml
index 436b75c..53faa8d 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -2,8 +2,21 @@
 name = "forcebot-rs-v2"
 version = "0.1.0"
 edition = "2021"
+default-run = "forcebot-rs-v2"
 
 [dependencies]
 dotenv = "0.15.0"
 tokio = { version = "1.33.0", features = ["full"] }
-twitch-irc = "5.0.1"
\ No newline at end of file
+twitch-irc = "5.0.1"
+
+# [[bin]]
+# name = "simple_bot"
+# path = "src/simple_bot.rs"
+
+# [[bin]]
+# name = "simple_bot_listener"
+# path = "src/simple_bot_listener.rs"
+
+# [lib]
+# name = "botlib"
+# path = "src/lib.rs"
\ No newline at end of file
diff --git a/readme.md b/readme.md
index e77154e..4af0b0c 100644
--- a/readme.md
+++ b/readme.md
@@ -2,7 +2,7 @@ Twitch chat bot written in rust
 
 # Quick Start 
 
-Runs the bot's binary crate
+Run a Simple bot with Built in functionality 
 
 1. Generate a twitch access token
 
@@ -25,16 +25,32 @@ bot_admins=ADMIN
 cargo run
 ```
 
+# Binary Crates
+
+## Simple Bot
+Run a simple bot that logs into chat based on env
+
+```
+cargo run --bin simple_bot
+```
+
+## Simple Bot with Example Custom Listener
+Run a bot with some custom listeners
+
+```
+cargo run --bin simple_bot_listener
+```
+
+
+
 # Example Code
 
-**Quick Start Main**
+## Simple Bot
 
 Uses Env defined variables to create and run the bot
 
 ```rust
-use botcore::bot::Bot;
-
-mod botcore;
+use forcebot_rs_v2::botcore::bot::Bot;
 
 #[tokio::main]
 pub async fn main() {
@@ -46,10 +62,72 @@ pub async fn main() {
     bot.run().await;
 
 }
+
+```
+
+## Custom Bot with listener
+Bot with a simple listener 
+
+Example listener listens for a moderator badge and reply in chat 
+
+```rust
+use std::sync::Arc;
+
+use forcebot_rs_v2::botcore::{bot::Bot, bot_objects::listener::asyncfn_box};
+use forcebot_rs_v2::botcore::bot_objects::listener::Listener;
+use twitch_irc::message::ServerMessage;
+
+
+#[tokio::main]
+pub async fn main() {
+
+    /* Create the bot using env */
+    let mut bot = Bot::new();
+
+    /* 1. Create a new blank Listener */
+    let mut listener = Listener::new();
+
+    /* 2. Set a trigger condition callback  */
+    listener.set_trigger_cond_fn(
+        |_:Arc<Bot>,message:ServerMessage| 
+            if let ServerMessage::Privmsg(msg) = message {
+                for badge in msg.badges {
+                    if matches!(badge, x if x.name == "moderator") {
+                        return true;
+                    }
+                } 
+                false
+            } else { false }
+    );
+
+    /* 3. Define an async fn callback execution */
+    async fn execbody(bot:Arc<Bot>,message:ServerMessage) -> Result<String,String> {
+        if let ServerMessage::Privmsg(msg) = message {
+            match bot.client.say_in_reply_to(&msg, String::from("test")).await {
+                Ok(_) => return Result::Ok("Success".to_string()) ,
+                Err(_) => return Result::Err("Not Valid message type".to_string()) 
+            }
+        }
+        Result::Err("Not Valid message type".to_string()) 
+    }
+
+    /* 4. Set the execution body using `async_box()`  */
+    listener.set_exec_fn(asyncfn_box(execbody));
+
+    /* 5. Load the Listener into the bot */
+    bot.load_listener(listener);
+
+    /* Run the bot */
+    bot.run().await;
+
+}
+
 ```
 
 # Crate Rust Documentation 
 
+Create Crate documentation
+
 Clean Build Documentation 
 ```
 cargo clean && cargo doc
diff --git a/src/bin/simple_bot.rs b/src/bin/simple_bot.rs
new file mode 100644
index 0000000..674a5d9
--- /dev/null
+++ b/src/bin/simple_bot.rs
@@ -0,0 +1,24 @@
+//! Example simple Binary crate that creates & runs bot based on `.env`
+//! Be sure the followig is defined in `.env` 
+//! - login_name
+//! - access_token
+//! - bot_channels
+//! - prefix
+//! - bot_admins
+//! 
+//! Bot access tokens be generated here - 
+//! - Get a Bot Chat Token here - <https://twitchtokengenerator.com>
+//! - More Info - <https://dev.twitch.tv/docs/authentication>
+
+use forcebot_rs_v2::botcore::bot::Bot;
+
+#[tokio::main]
+pub async fn main() {
+
+    /* 1. Create the bot using env */
+    let bot = Bot::new();
+
+    /* 2. Run the bot */
+    bot.run().await;
+
+}
diff --git a/src/bin/simple_bot_listener.rs b/src/bin/simple_bot_listener.rs
new file mode 100644
index 0000000..b2a9141
--- /dev/null
+++ b/src/bin/simple_bot_listener.rs
@@ -0,0 +1,66 @@
+//! Simple bot with a custom listeners that listens for moderators and respond to the moderator
+//! 
+//! Be sure the followig is defined in `.env` 
+//! - login_name
+//! - access_token
+//! - bot_channels
+//! - prefix
+//! - bot_admins
+//! 
+//! Bot access tokens be generated here - 
+//! - Get a Bot Chat Token here - <https://twitchtokengenerator.com>
+//! - More Info - <https://dev.twitch.tv/docs/authentication>
+
+use std::sync::Arc;
+
+use forcebot_rs_v2::botcore::{bot::Bot, bot_objects::listener::asyncfn_box};
+use forcebot_rs_v2::botcore::bot_objects::listener::Listener;
+use twitch_irc::message::ServerMessage;
+
+
+#[tokio::main]
+pub async fn main() {
+
+    /* Create the bot using env */
+    let mut bot = Bot::new();
+
+    /* 1. Create a new blank Listener */
+    let mut listener = Listener::new();
+
+    /* 2. Set a trigger condition function for listener */
+
+    listener.set_trigger_cond_fn(
+        |_:Arc<Bot>,message:ServerMessage| 
+            if let ServerMessage::Privmsg(msg) = message {
+                // dbg!(msg.clone());
+                for badge in msg.badges {
+                    if matches!(badge, x if x.name == "moderator") {
+                        // dbg!("moderator found");
+                        return true;
+                    }
+                } 
+                false
+            } else { false }
+    );
+
+    /* 3. Define an async fn callback execution */
+    async fn execbody(bot:Arc<Bot>,message:ServerMessage) -> Result<String,String> {
+        if let ServerMessage::Privmsg(msg) = message {
+            match bot.client.say_in_reply_to(&msg, String::from("test")).await {
+                Ok(_) => return Result::Ok("Success".to_string()) ,
+                Err(_) => return Result::Err("Not Valid message type".to_string()) 
+            }
+        }
+        Result::Err("Not Valid message type".to_string()) 
+    }
+
+    /* 4. Set and Store the execution body using `async_box()`  */
+    listener.set_exec_fn(asyncfn_box(execbody));
+
+    /* 5. Load the listener into the bot */
+    bot.load_listener(listener);
+
+    /* Run the bot */
+    bot.run().await;
+
+}
diff --git a/src/botcore.rs b/src/botcore.rs
index 96f1e66..269a97a 100644
--- a/src/botcore.rs
+++ b/src/botcore.rs
@@ -1 +1,2 @@
-pub mod bot;
\ No newline at end of file
+pub mod bot;
+pub mod bot_objects;
\ No newline at end of file
diff --git a/src/botcore/bot.rs b/src/botcore/bot.rs
index f01a489..e21de83 100644
--- a/src/botcore/bot.rs
+++ b/src/botcore/bot.rs
@@ -3,23 +3,30 @@
 use tokio::sync::{mpsc::UnboundedReceiver, Mutex};
 use twitch_irc::{login::StaticLoginCredentials, message::ServerMessage, SecureTCPTransport, TwitchIRCClient};
 use dotenv::dotenv;
-use std::env;
+use std::{env, sync::Arc};
+
+use super::bot_objects::listener::Listener;
+
+
 
 /// Twitch chat bot
-pub struct Bot {
+pub struct Bot 
+{
     /// Prefix for commands
     _prefix: char,
     /// inbound chat msg stream
     incoming_msgs: Mutex<UnboundedReceiver<ServerMessage>>,
     /// outbound chat client msg stream
-    client: TwitchIRCClient<SecureTCPTransport,StaticLoginCredentials>,
+    pub client: TwitchIRCClient<SecureTCPTransport,StaticLoginCredentials>,
     /// joined channels
     botchannels: Vec<String>,
+    /// listeners
+    listeners: Vec<Listener>,
 }
 
 
-impl Bot {
-
+impl Bot
+{
     /// Creates a new `Bot` using env variables
     /// 
     /// Be sure the following is defined in an `.env` file
@@ -79,6 +86,7 @@ impl Bot {
              incoming_msgs : Mutex::new(incoming_messages),
              client,
              botchannels : botchannels_all,
+             listeners : vec![],
         }
     }
 
@@ -88,17 +96,35 @@ impl Bot {
         for chnl in &self.botchannels {
             self.client.join(chnl.to_owned()).unwrap();
         }
+        
+
+        let bot = Arc::new(self);
 
         let join_handle = tokio::spawn(async move {
-            let mut in_msgs_lock = self.incoming_msgs.lock().await;
+            
+            let mut in_msgs_lock = bot.incoming_msgs.lock().await;
+            
             while let Some(message) = in_msgs_lock.recv().await {
-                //sprintln!("Received message: {:?}", message);
-                dbg!("Received message: {:?}", message);
+                // dbg!("Received message: {:?}", message.clone());
+                
+                for listener in &(*bot).listeners {
+                    
+                    let a = listener.clone();
+                    if a.cond_triggered(bot.clone(),message.clone()) {
+                        
+                        let _ = listener.execute_fn(bot.clone(),message.clone()).await;
+                    }
+                }
             }
             drop(in_msgs_lock);
         });
         
         join_handle.await.unwrap();
     }
+
+    /// Loads a `Listener` into the bot
+    pub fn load_listener(&mut self,l : Listener) {
+        self.listeners.push(l);
+    }
     
 }
\ No newline at end of file
diff --git a/src/botcore/bot_objects.rs b/src/botcore/bot_objects.rs
new file mode 100644
index 0000000..baefb0b
--- /dev/null
+++ b/src/botcore/bot_objects.rs
@@ -0,0 +1 @@
+pub mod listener;
\ No newline at end of file
diff --git a/src/botcore/bot_objects/listener.rs b/src/botcore/bot_objects/listener.rs
new file mode 100644
index 0000000..0f953c4
--- /dev/null
+++ b/src/botcore/bot_objects/listener.rs
@@ -0,0 +1,83 @@
+use std::sync::Arc;
+
+use twitch_irc::message::ServerMessage;
+
+use crate::botcore::bot::Bot;
+
+/// Bot `Listener`` that stores trigger condition callback and a execution functon
+/// 
+/// Use `asyncfn_box()` on custom async execution bodies
+#[derive(Clone)]
+pub struct Listener
+{
+    trigger_cond_fn : fn(Arc<Bot>,ServerMessage) -> bool,
+    exec_fn : Arc<ExecBody>,
+}
+
+impl Listener
+{
+
+    /// Creates a new empty `Listener` . 
+    /// Call `set_trigger_cond_fn()` and `set_exec_fn()` to trigger & execution function callbacks
+    pub fn new() -> Listener {
+
+        async fn execbody(_:Arc<Bot>,_:ServerMessage) -> Result<String,String> {Result::Ok("success".to_string()) }
+
+        Listener {
+            trigger_cond_fn : |_:Arc<Bot>,_:ServerMessage| false,
+            exec_fn : Arc::new(asyncfn_box(execbody))
+        }
+    }
+
+    /// set a trigger conditin callback that returns true if the listener shoud trigger
+    pub fn set_trigger_cond_fn(&mut self,cond_fn: fn(Arc<Bot>,ServerMessage) -> bool) {
+        self.trigger_cond_fn = cond_fn;
+    }
+
+    /// sets the execution body of the listener for when it triggers
+    /// 
+    /// Use`asyncfn_box()` on the async fn when storing
+    /// 
+    /// Example - 
+    /// ```rust
+    /// /* 1. Create a new blank Listener */
+    /// let mut listener = Listener::new();
+    ///
+    /// /* 2. define an async function */
+    /// async fn execbody(_:Arc<Bot>,_:ServerMessage) -> Result<String,String> {Result::Ok("success".to_string()) }
+    /// 
+    /// /* 3. Set and Store the execution body using `async_box()`  */
+    /// listener.set_exec_fn(asyncfn_box(execbody));
+    /// ```
+    /// 
+    pub fn set_exec_fn(&mut self,exec_fn:ExecBody ) {
+        self.exec_fn = Arc::new(exec_fn);
+    }
+
+    /// checks if the trigger condition is met
+    pub fn cond_triggered(&self,bot:Arc<Bot>,msg:ServerMessage) -> bool {
+        (self.trigger_cond_fn)(bot,msg)
+    }
+
+    /// executes the listeners executon body
+    pub async fn execute_fn(&self,bot:Arc<Bot>,msg:ServerMessage) -> Result<String, String> {
+        // (self.exec_fn)(bot,msg)
+        (self.exec_fn)(bot,msg).await
+    }
+}
+
+
+use std::boxed::Box;
+use std::future::Future;
+use std::pin::Pin;
+
+pub type ExecBody = Box<
+    dyn Fn(Arc<Bot>,ServerMessage) -> Pin<Box<dyn Future<Output = Result<String,String>> + Send>> + Send + Sync,
+>;
+
+pub fn asyncfn_box<T>(f: fn(Arc<Bot>,ServerMessage) -> T) -> ExecBody
+where
+    T: Future<Output = Result<String,String>> + Send + 'static,
+{
+    Box::new(move |a,b| Box::pin(f(a,b)))
+}
\ No newline at end of file
diff --git a/src/lib.rs b/src/lib.rs
new file mode 100644
index 0000000..ce1adca
--- /dev/null
+++ b/src/lib.rs
@@ -0,0 +1,82 @@
+//! `forcebot-rs-v2` : Twitch chat bot written in rust
+//! Customize by adding additional bot objects
+//! 
+//! # Example Simple Bot
+//! ```
+//! use forcebot_rs_v2::botcore::bot::Bot;
+//!
+//! #[tokio::main]
+//!pub async fn main() {
+//!
+//!    /* 1. Create the bot using env */
+//!    let bot = Bot::new();
+//!
+//!    /* 2. Run the bot */
+//!    bot.run().await;
+//!
+//!}
+//!
+//! ```
+//! 
+//! # Example Code Add Listener
+//! 
+//! Bot with a simple listener 
+//! 
+//! Example listener listens for a moderator badge and reply in chat 
+//! 
+//! ```
+//! use std::sync::Arc;
+//! 
+//! use forcebot_rs_v2::botcore::{bot::Bot, bot_objects::listener::asyncfn_box};
+//! use forcebot_rs_v2::botcore::bot_objects::listener::Listener;
+//! use twitch_irc::message::ServerMessage;
+//! 
+//! 
+//! #[tokio::main]
+//! pub async fn main() {
+//! 
+//!     /* Create the bot using env */
+//!     let mut bot = Bot::new();
+//! 
+//!     /* 1. Create a new blank Listener */
+//!     let mut listener = Listener::new();
+//! 
+//!     /* 2. Set a trigger condition callback  */
+//!     listener.set_trigger_cond_fn(
+//!         |_:Arc<Bot>,message:ServerMessage| 
+//!             if let ServerMessage::Privmsg(msg) = message {
+//!                 for badge in msg.badges {
+//!                     if matches!(badge, x if x.name == "moderator") {
+//!                         return true;
+//!                     }
+//!                 } 
+//!                 false
+//!             } else { false }
+//!     );
+//! 
+//!    /* 3. Define an async fn callback execution */
+//!    async fn execbody(bot:Arc<Bot>,message:ServerMessage) -> Result<String,String> {
+//!        if let ServerMessage::Privmsg(msg) = message {
+//!            match bot.client.say_in_reply_to(&msg, String::from("test")).await {
+//!                Ok(_) => return Result::Ok("Success".to_string()) ,
+//!                Err(_) => return Result::Err("Not Valid message type".to_string()) 
+//!            }
+//!        }
+//!        Result::Err("Not Valid message type".to_string()) 
+//!    }
+//! 
+//!     /* 4. Set the execution body using `async_box()`  */
+//!     listener.set_exec_fn(asyncfn_box(execbody));
+//! 
+//!     /* 5. Load the Listener into the bot */
+//!     bot.load_listener(listener);
+//! 
+//!     /* Run the bot */
+//!     bot.run().await;
+//! 
+//! }
+//! ```
+//! 
+//! 
+
+pub mod botcore;
\ No newline at end of file
diff --git a/src/main.rs b/src/main.rs
index 93f840e..ebbe171 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -10,9 +10,8 @@
 //! - Get a Bot Chat Token here - <https://twitchtokengenerator.com>
 //! - More Info - <https://dev.twitch.tv/docs/authentication>
 
-pub use botcore::bot::Bot;
+use forcebot_rs_v2::botcore::bot::Bot;
 
-mod botcore;
 
 #[tokio::main]
 pub async fn main() {