diff --git a/Cargo.toml b/Cargo.toml
index 8eace12..c4ca5d9 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -8,3 +8,5 @@ chumsky = "0.9.0"
 ariadne = "0.2"
 laddertypes = { path = "../lib-laddertypes", features = ["pretty"] }
 tiny-ansi = { version = "0.1.0" }
+clap = { version = "4.5.37", features = ["derive"] }
+walkdir = "2.5.0"
diff --git a/src/c_gen/gen_lib.rs b/src/c_gen/gen_lib.rs
new file mode 100644
index 0000000..fa2ce88
--- /dev/null
+++ b/src/c_gen/gen_lib.rs
@@ -0,0 +1,74 @@
+use {
+    super::types::get_c_repr_arg_type, crate::{c_gen::LdmcCTargetMorph, LdmcPrimMorph}, laddertypes::{morphism::MorphismInstance, parser::*, TypeDict}, std::collections::HashMap
+};
+
+pub fn generate_lib(
+    dict: &mut impl TypeDict,
+    morphisms: Vec< (String, MorphismInstance<LdmcPrimMorph>) >
+) -> Result<String, ()> {
+    let mut target = LdmcCTargetMorph::new();
+    let mut wrappers = String::new();
+
+    for (name, morph) in morphisms {
+        match target.add_instantiation(dict, morph) {
+            Ok(inst) => {
+                if name == "main" {
+                    let mut c_source = String::new();
+                    c_source.push_str(&format!(r#"
+                #include <unistd.h>
+
+                int main() {{
+                    uint8_t bufIn[4096];
+                    uint8_t bufOut[4096];"#));
+
+                    let (src_top, src_floor) = inst.ty.src_type.get_floor_type();
+                    if src_floor == dict.parse_desugared("<Seq~<ValueTerminated 0> native.UInt8>").expect("").sugar(dict) {
+                        c_source.push_str("scanf(\"%s\", bufIn);");
+                    } else {
+                        c_source.push_str("read(0, bufIn, sizeof(bufIn));");
+                    }
+
+                    c_source.push_str(&format!(r#"FUSE( {}, (void const*)bufIn, (void*)bufOut );"#, inst.instantiated_symbol_name(dict, &HashMap::new())));
+
+                    if let Ok(ψ) = laddertypes::constraint_system::subtype_unify(
+                        &inst.ty.src_type,
+                        &dict.parse_desugared("<Seq~<ValueTerminated 0> native.UInt8>").expect("").sugar(dict)
+                    ) {
+                        c_source.push_str("printf(\"%s\\n\", bufOut);");
+                    } else {
+                        c_source.push_str("write(1, bufOut, sizeof(bufOut));");
+                    }
+                    c_source.push_str("
+                    return 0;
+                }");
+                    wrappers.push_str(&c_source);
+                } else {
+                    target.add_type(dict, inst.ty.src_type.clone());
+                    target.add_type(dict, inst.ty.dst_type.clone());
+
+                    wrappers.push_str(&format!("
+                        int {} (
+                            {} const * restrict src,
+                            {} * restrict dst
+                        ) {{
+                            return {}( (void*)src, (void*)dst );
+                        }}
+                    ", name,
+                        get_c_repr_arg_type(dict, &inst.ty.src_type),
+                        get_c_repr_arg_type(dict, &inst.ty.dst_type),
+                        inst.instantiated_symbol_name(dict, &HashMap::new())
+                    ));
+                }
+            }
+            Err(_err) => {
+                eprintln!("failed to create morphism instatiation");
+                return Err(());
+            }
+        }
+    }
+
+    let mut c_source = target.into_c_source(dict);
+    c_source.push_str(&wrappers);
+
+    Ok(c_source)
+}
diff --git a/src/c_gen/gen_main.rs b/src/c_gen/gen_main.rs
deleted file mode 100644
index 70847ea..0000000
--- a/src/c_gen/gen_main.rs
+++ /dev/null
@@ -1,49 +0,0 @@
-use {
-    laddertypes::{TypeDict, morphism::MorphismInstance, parser::*},
-    crate::LdmcPrimMorph,
-    crate::c_gen::LdmcCTargetMorph,
-    std::collections::HashMap,
-};
-
-pub fn generate_main(dict: &mut impl TypeDict, morph: MorphismInstance<LdmcPrimMorph>) -> Result<String, ()> {
-    let mut target = LdmcCTargetMorph::new();
-    let ty = morph.get_type();
-    match target.add_instantiation(dict, morph) {
-        Ok(inst) => {
-            let mut c_source = target.into_c_source(dict);
-
-            c_source.push_str(&format!(r#"
-        #include <unistd.h>
-
-        int main() {{
-            uint8_t bufIn[4096];
-            uint8_t bufOut[4096];"#));
-
-            let (src_top, src_floor) = ty.src_type.get_floor_type();
-            if src_floor == dict.parse_desugared("<Seq~<ValueTerminated 0> native.UInt8>").expect("").sugar(dict) {
-                c_source.push_str("scanf(\"%s\", bufIn);");
-            } else {
-                c_source.push_str("read(0, bufIn, sizeof(bufIn));");
-            }
-
-            c_source.push_str(&format!(r#"FUSE( {}, (void const*)bufIn, (void*)bufOut );"#, inst.instantiated_symbol_name(dict, &HashMap::new())));
-
-            if let Ok(ψ) = laddertypes::constraint_system::subtype_unify(
-                &ty.src_type,
-                &dict.parse_desugared("<Seq~<ValueTerminated 0> native.UInt8>").expect("").sugar(dict)
-            ) {
-                c_source.push_str("printf(\"%s\\n\", bufOut);");
-            } else {
-                c_source.push_str("write(1, bufOut, sizeof(bufOut));");
-            }
-            c_source.push_str("
-            return 0;
-        }");
-            Ok(c_source)
-        }
-        Err(err) => {
-            eprintln!("failed to create morphism instatiation");
-            Err(())
-        }
-    }
-}
diff --git a/src/c_gen/mod.rs b/src/c_gen/mod.rs
index f8c11f9..cf994c5 100644
--- a/src/c_gen/mod.rs
+++ b/src/c_gen/mod.rs
@@ -1,6 +1,6 @@
 pub mod types;
 pub mod morph;
-pub mod gen_main;
+pub mod gen_lib;
 
 pub use {
     morph::target_morph::LdmcCTargetMorph
diff --git a/src/main.rs b/src/main.rs
index 01df9a7..d1e114a 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -9,33 +9,66 @@ use {
     crate::{
         morphism::LdmcPrimMorph,
         parser::morphism_base_parser,
-    },
-    ariadne::{Color, Label, Report, ReportKind, Source},
-    chumsky::prelude::*,
-    laddertypes::{
+    }, ariadne::{Color, Label, Report, ReportKind, Source}, chumsky::prelude::*, clap::{Parser, Subcommand}, laddertypes::{
         morphism::MorphismType,
         parser::ParseLadderType, BimapTypeDict
-    },
-    std::{sync::{Arc, RwLock}},
-    tiny_ansi::TinyAnsi
+    }, parser::morphism_type_parser, std::{path::PathBuf,
+    sync::{Arc, RwLock}}, tiny_ansi::TinyAnsi,
+    walkdir::WalkDir
 };
 
-fn main() {
-    let mut type_dict = Arc::new(RwLock::new(BimapTypeDict::new()));
+#[derive(Parser, Debug)]
+#[command(version, about, long_about = None)]
+struct Args {
+    #[arg(short='b', long)]
+    morphism_base: Vec<PathBuf>,
 
+    #[arg(short='m', long="morph")]
+    morphisms: Vec<String>
+}
+
+fn main() {
+    let args = Args::parse();
+    let mut type_dict = Arc::new(RwLock::new(BimapTypeDict::new()));
     let mut morphism_base = laddertypes::morphism_base::MorphismBase::<LdmcPrimMorph>::new();
 
-    let mut args = std::env::args().skip(1);
-    let src_type_arg = args.next().expect("src type expected");
-    let dst_type_arg = args.next().expect("dst type expected");
+    // 1. load morphism base
+    let mut mb_paths = args.morphism_base;
 
-    for mb_path in args {
+    // 1.1. pfade ermitteln
+    let env_var = "MORPHISM_BASE";
+    let suffix = ".morphism-base";
+
+    match std::env::var(env_var) {
+        Ok(path_str) => {
+            let path = std::path::Path::new(&path_str);
+            if path.is_dir() {
+                for entry in WalkDir::new(path)
+                    .into_iter()
+                    .filter_map(Result::ok)
+                    .filter(|e| e.path().is_file() && e.path().extension().map_or(false, |ext| ext == &suffix[1..]))
+                {
+                    mb_paths.push(entry.path().into());
+                }
+            } else {
+                eprintln!("morphism-base path is not a directory: {:?}", path);
+            }
+        }
+        Err(e) => {
+            eprintln!("failed to read environment variable {}: {}", env_var, e);
+        }
+    }
+
+    // 1.2. read files
+    for mb_path in mb_paths {
         let src = std::fs::read_to_string(mb_path.clone()).expect("failed to read morphism base");
+
+        use chumsky::Parser;
         let result = morphism_base_parser(type_dict.clone()).parse(src.clone());
         match result {
             Ok((includes, morphisms)) => {
                 println!("{}",includes);
-                eprintln!("[{}] parse ok.", mb_path.bright_yellow());
+                eprintln!("[{}] parse ok.", mb_path.to_str().unwrap().bright_yellow());
                 for m in morphisms {
                     morphism_base.add_morphism(m);
                 }
@@ -57,10 +90,17 @@ fn main() {
         }
     }
 
-    let src_type = type_dict.parse( src_type_arg.as_str() ).expect("");
-    let dst_type = type_dict.parse( dst_type_arg.as_str() ).expect("");
+    // 2. Generate Morphisms
+    let mut instances = Vec::new();
+    for morph_decl in args.morphisms.iter() {
+        use chumsky::Parser;
+        if let Ok((name, src_type, dst_type)) = morphism_type_parser(type_dict.clone()).parse(morph_decl.as_str()) {
+            let ty = MorphismType{ src_type, dst_type };
+            instances.push( (name, morphism_base.get_morphism_instance( &ty ).expect("failed to find morphism")) );
+        }
+    }
 
-    let ty = MorphismType{ src_type, dst_type };
-    let m = morphism_base.get_morphism_instance( &ty ).expect("failed to find morphism");
-    println!("{}", crate::c_gen::gen_main::generate_main(&mut type_dict, m).expect("failed to generate main function"));
+    println!("{}",
+        crate::c_gen::gen_lib::generate_lib(&mut type_dict, instances).expect("failed to generate main function")
+    );
 }
diff --git a/src/parser.rs b/src/parser.rs
index ef2acff..24ca0a9 100644
--- a/src/parser.rs
+++ b/src/parser.rs
@@ -1,7 +1,7 @@
 use {
     crate::morphism::LdmcPrimMorph, chumsky::{
         prelude::*, text::*
-    }, laddertypes::{morphism::MorphismType, parser::*, BimapTypeDict, TypeDict}, std::sync::{Arc, RwLock}
+    }, laddertypes::{TypeTerm, morphism::MorphismType, parser::*, BimapTypeDict, TypeDict}, std::sync::{Arc, RwLock}
 };
 
 /* morphism-base text format:
@@ -59,8 +59,8 @@ pub fn morphism_base_parser(
                 ty_args.push((var_id, kind));
             }
 
-            let src_type = type_dict.parse_desugared(&src_type.iter().collect::<String>()).expect("couldnt parse src type").sugar(&mut *type_dict);
-            let dst_type = type_dict.parse_desugared(&dst_type.iter().collect::<String>()).expect("couldnt parse dst type").sugar(&mut *type_dict);
+            let src_type = type_dict.parse(&src_type.iter().collect::<String>()).expect("couldnt parse src type");
+            let dst_type = type_dict.parse(&dst_type.iter().collect::<String>()).expect("couldnt parse dst type");
 
             LdmcPrimMorph {
                 symbol,
@@ -76,3 +76,25 @@ pub fn morphism_base_parser(
 
     )
 }
+
+pub fn morphism_type_parser(
+    mut type_dict: Arc<RwLock< BimapTypeDict >>
+) -> impl Parser<char, (String, TypeTerm, TypeTerm), Error = Simple<char>> {
+    ident()
+        .padded()
+        .then(just(":").ignored())
+        .then(
+            take_until(just("-->").ignored())
+        )
+        .then(take_until(end()))
+        .map({
+            let type_dict = type_dict.clone();
+            move |((name, src_type), dst_type)| {
+                (
+                    name.0,
+                    type_dict.clone().parse(&src_type.0.iter().collect::<String>()).expect("parse type"),
+                    type_dict.clone().parse(&dst_type.0.iter().collect::<String>()).expect("parse type")
+                )
+            }
+        })
+}