diff --git a/libopenfpga/libopenfpgashell/src/shell.h b/libopenfpga/libopenfpgashell/src/shell.h
index 0f83b4e46..0d746f931 100644
--- a/libopenfpga/libopenfpgashell/src/shell.h
+++ b/libopenfpga/libopenfpgashell/src/shell.h
@@ -61,6 +61,7 @@ class Shell {
       STANDARD,
       SHORT,
       BUILTIN,
+      MACRO,
       NUM_EXEC_FUNC_TYPES
     };
   public: /* Constructor */
@@ -89,6 +90,7 @@ class Shell {
      * 1. Standard function, including the data exchange <T> and commands
      * 2. Short function, including only the data exchange <T>
      * 3. Built-in function, including only the shell envoriment variables
+     * 4. Marco function, which directly call a macro function without command parsing
      * Users just need to specify the function object and its type will be automatically inferred
      */
     void set_command_execute_function(const ShellCommandId& cmd_id,
@@ -97,6 +99,8 @@ class Shell {
                                       std::function<void(T&)> exec_func);
     void set_command_execute_function(const ShellCommandId& cmd_id,
                                       std::function<void()> exec_func);
+    void set_command_execute_function(const ShellCommandId& cmd_id,
+                                      std::function<void(int, char**)> exec_func);
     void set_command_dependency(const ShellCommandId& cmd_id,
                                 const std::vector<ShellCommandId> cmd_dependency);
     ShellCommandClassId add_command_class(const char* name);
@@ -150,10 +154,12 @@ class Shell {
      * 1. Standard function, including the data exchange <T> and commands
      * 2. Short function, including only the data exchange <T>
      * 3. Built-in function, including only the shell envoriment variables
+     * 4. Marco function, which directly call a macro function without command parsing
      */
     vtr::vector<ShellCommandId, std::function<void(T&, const Command&, const CommandContext&)>> command_standard_execute_functions_;  
     vtr::vector<ShellCommandId, std::function<void(T&)>> command_short_execute_functions_;  
     vtr::vector<ShellCommandId, std::function<void()>> command_builtin_execute_functions_;  
+    vtr::vector<ShellCommandId, std::function<void(int, char**)>> command_macro_execute_functions_;  
 
     /* Type of execute functions for each command.
      * This is supposed to be an internal data ONLY 
diff --git a/libopenfpga/libopenfpgashell/src/shell.tpp b/libopenfpga/libopenfpgashell/src/shell.tpp
index ac1621029..65843afc8 100644
--- a/libopenfpga/libopenfpgashell/src/shell.tpp
+++ b/libopenfpga/libopenfpgashell/src/shell.tpp
@@ -128,6 +128,7 @@ ShellCommandId Shell<T>::add_command(const Command& cmd, const char* descr) {
   command_standard_execute_functions_.emplace_back();
   command_short_execute_functions_.emplace_back();
   command_builtin_execute_functions_.emplace_back();
+  command_macro_execute_functions_.emplace_back();
   command_dependencies_.emplace_back();
 
   /* Register the name in the name2id map */
@@ -173,6 +174,14 @@ void Shell<T>::set_command_execute_function(const ShellCommandId& cmd_id,
   command_builtin_execute_functions_[cmd_id] = exec_func;
 }
 
+template<class T>
+void Shell<T>::set_command_execute_function(const ShellCommandId& cmd_id, 
+                                            std::function<void(int, char**)> exec_func) {
+  VTR_ASSERT(true == valid_command_id(cmd_id));
+  command_execute_function_types_[cmd_id] = MACRO;
+  command_macro_execute_functions_[cmd_id] = exec_func;
+}
+
 template<class T>
 void Shell<T>::set_command_dependency(const ShellCommandId& cmd_id,
                                       const std::vector<ShellCommandId> dependent_cmds) {
@@ -337,7 +346,28 @@ void Shell<T>::execute_command(const char* cmd_line,
 
   /* TODO: Check the dependency graph to see if all the prequistics have been met */
 
-  /* Find the command! Parse the options */
+  /* Find the command! Parse the options 
+   * Note:
+   * Macro command will not be parsed! It will be directly executed
+   */
+  if (MACRO == command_execute_function_types_[cmd_id]) {
+    /* Convert the tokens from string to char */
+    char** argv = (char**)malloc(tokens.size() * sizeof(char*));
+    for (size_t itok = 0; itok < tokens.size(); ++itok) {
+      argv[itok] = (char*)malloc((tokens[itok].length() + 1) * sizeof(char));
+      strcpy(argv[itok], tokens[itok].c_str());
+    }
+    /* Execute the marco function */
+    command_macro_execute_functions_[cmd_id](tokens.size(), argv);
+    /* Free the argv */
+    for (size_t itok = 0; itok < tokens.size(); ++itok) {
+      free(argv[itok]);
+    }
+    free(argv);
+    /* Finish for macro command, return */
+    return;
+  }
+ 
   if (false == parse_command(tokens, commands_[cmd_id], command_contexts_[cmd_id])) {
     /* Echo the command */
     print_command_options(commands_[cmd_id]);
@@ -358,6 +388,7 @@ void Shell<T>::execute_command(const char* cmd_line,
   case BUILTIN:
     command_builtin_execute_functions_[cmd_id]();
     break;
+  /* MACRO should be executed eariler in this function. It should not appear here */
   default:
     /* This is not allowed! Error out */
     VTR_LOG("Invalid type of execute function for command '%s'!\n",
diff --git a/libopenfpga/libopenfpgashell/test/test_shell.cpp b/libopenfpga/libopenfpgashell/test/test_shell.cpp
index 8fc00f055..f84a910d5 100644
--- a/libopenfpga/libopenfpgashell/test/test_shell.cpp
+++ b/libopenfpga/libopenfpgashell/test/test_shell.cpp
@@ -27,6 +27,15 @@ void shell_execute_print(ShellContext& context) {
   VTR_LOG("a=%d\n", context.a);
 }
 
+static
+void shell_execute_print_macro(int argc, char** argv) {
+  VTR_LOG("Number of arguments: %d\n", argc);
+  VTR_LOG("Detailed arguments:\n");
+  for (int iarg = 0; iarg < argc; ++iarg) {
+    VTR_LOG("\t[%d]: %s\n", iarg, argv[iarg]);
+  }
+}
+
 int main(int argc, char** argv) {
   /* Create the command to launch shell in different modes */
   Command start_cmd("test_shell");
@@ -97,6 +106,15 @@ int main(int argc, char** argv) {
   shell.set_command_class(shell_cmd_print_id, arith_cmd_class);
   shell.set_command_execute_function(shell_cmd_print_id, shell_execute_print);
 
+  /* Create a macro command of 'print_macro' 
+   * This function will print the value of an internal variable of ShellContext 
+   */
+  Command shell_cmd_print_macro("print_macro");
+  ShellCommandId shell_cmd_print_macro_id = shell.add_command(shell_cmd_print_macro, "A macro function to print arguments");
+  shell.set_command_class(shell_cmd_print_macro_id, arith_cmd_class);
+  shell.set_command_execute_function(shell_cmd_print_macro_id, shell_execute_print_macro);
+
+
   /* Add a new class of commands */
   ShellCommandClassId basic_cmd_class = shell.add_command_class("Basic");
 
diff --git a/libopenfpga/libopenfpgashell/test_script/test.openfpga b/libopenfpga/libopenfpgashell/test_script/test.openfpga
index 992001a7e..8122e2a17 100644
--- a/libopenfpga/libopenfpgashell/test_script/test.openfpga
+++ b/libopenfpga/libopenfpgashell/test_script/test.openfpga
@@ -6,4 +6,7 @@ set --value 5
 
 print # Print out the value
 
+# Test macro arguments
+print_macro arch blif
+
 exit # Finish