diff --git a/src/Rust/vvs_cli/src/args.rs b/src/Rust/vvs_cli/src/args.rs
index 08e8ea60213e4e3f515ba51c7885fae1556f9a55..5f74ba2f279764c02b3187e096660c12d14d3839 100644
--- a/src/Rust/vvs_cli/src/args.rs
+++ b/src/Rust/vvs_cli/src/args.rs
@@ -21,7 +21,7 @@ pub struct Args {
     /// touch or call fields from vivy that begins by underscores.
     #[arg( action       = clap::ArgAction::Set
          , id           = "script.vvs"
-         , value_parser = FileTypeValueParser::new("vvs")
+         , value_parser = FileTypeValueParser::new(vvs_lang::VIVY_SCRIPT_EXTENSION)
     )]
     pub script: Option<PathBuf>,
 
diff --git a/src/Rust/vvs_cli/src/main.rs b/src/Rust/vvs_cli/src/main.rs
index 6898acb3c307f83cd855f24b3962c25347ccc97a..c8030eca5a55488bcfd5c52fc8d87096ac55f166 100644
--- a/src/Rust/vvs_cli/src/main.rs
+++ b/src/Rust/vvs_cli/src/main.rs
@@ -2,7 +2,7 @@
 
 //! The VivyScript cli
 
-use anyhow::{Context as _, Result};
+use anyhow::{Context, Result};
 use clap::{CommandFactory as _, Parser as _};
 use std::{fs, io, path::Path};
 use vvs_cli::{
@@ -52,15 +52,16 @@ fn main() -> Result<()> {
     }
 
     // Parse, build, execute the script.
-    let Some(script) = script else {
-        return Ok(Args::command().print_help()?);
+    let script = match script {
+        Some(script) => SourceCode::from_path(&script)?,
+        None => return Ok(Args::command().print_help()?),
     };
-
-    let output = FrontendPipeline::new(&SourceCode::from_path(&script)?)
+    println!("main module ........ {}", script.module().context("expected a valid module name")?);
+    let output = FrontendPipeline::new(&script)
         .passes(&[])
         .search(
             &SearchPath::from_iter(includes)
-                .with_script_folder(script.parent().context("expected the script to have a parent folder")?),
+                .with_script_folder(script.folder().context("expected the script to have a parent folder")?),
         )
         .options(options.as_ref())?
         .run()?;
diff --git a/src/Rust/vvs_lang/src/frontend_pipeline.rs b/src/Rust/vvs_lang/src/frontend_pipeline.rs
index 420739ad26ce82b00caff73df53de579c93f92d8..88746a344188ac678666971fb30ec86241f0c707 100644
--- a/src/Rust/vvs_lang/src/frontend_pipeline.rs
+++ b/src/Rust/vvs_lang/src/frontend_pipeline.rs
@@ -198,15 +198,15 @@ impl FromIterator<ImportAllResult> for ImportAllResult {
 
 impl<'a> FrontendPipeline<'a> {
     /// Create a new pipeline to parse, to check and do black magic.
-    pub fn new(SourceCode { name, code }: &'a SourceCode) -> Self {
-        log::debug!(target: "vvs_parser", "run script `{name}`");
+    pub fn new(source @ SourceCode { code, .. }: &'a SourceCode) -> Self {
+        log::debug!(target: "vvs_parser", "run script `{}`", source.module().unwrap());
         Self {
             program: Cow::Borrowed(code.as_ref()),
             options: None,
             imports: Default::default(),
             is_main: true,
             library: Rc::new(RefCell::new(Library::default())),
-            process_path: vec![ShortString::new(name.as_ref())],
+            process_path: vec![ShortString::new(source.module().unwrap())],
             search: &DEFAULT_SEARCH_PATH,
             passes: &[],
         }
diff --git a/src/Rust/vvs_lang/src/lib.rs b/src/Rust/vvs_lang/src/lib.rs
index 9cbc7b63c00c159dcc558ab1731e1027309a2dcf..30af3b33a3993072fbb236bc20d49a5793d7fcac 100644
--- a/src/Rust/vvs_lang/src/lib.rs
+++ b/src/Rust/vvs_lang/src/lib.rs
@@ -8,14 +8,26 @@ mod passes;
 mod search_path;
 mod symbol_table;
 
-use std::{borrow::Cow, fs, io, path::Path};
+use derive_more::Display;
+use std::{
+    borrow::Cow,
+    fs, io,
+    path::{Path, PathBuf},
+};
 
 pub use crate::{
-    error_report::ErrorReport, frontend_pipeline::*, main_program::*, passes::UserFrontendPass, search_path::SearchPath,
+    error_report::ErrorReport,
+    frontend_pipeline::*,
+    main_program::*,
+    passes::UserFrontendPass,
+    search_path::{SearchPath, VIVY_SCRIPT_EXTENSION},
 };
 
 /// The representation of a source file.
+#[derive(Display, Debug, Clone)]
+#[display("{code}")]
 pub struct SourceCode {
+    path: Option<PathBuf>,
     name: Cow<'static, str>,
     code: Cow<'static, str>,
 }
@@ -23,25 +35,37 @@ pub struct SourceCode {
 impl SourceCode {
     /// Create a new source file from a file.
     pub fn from_path(path: impl AsRef<Path>) -> io::Result<Self> {
+        let path = path.as_ref();
         Ok(Self {
             name: Cow::Owned(
-                path.as_ref()
-                    .file_name()
+                path.file_name()
                     .ok_or_else(|| io::Error::new(io::ErrorKind::Other, "path doesn't have a file name"))?
                     .to_string_lossy()
                     .to_string(),
             ),
-            code: Cow::Owned(fs::read_to_string(path.as_ref())?),
+            path: Some(path.to_path_buf()),
+            code: Cow::Owned(fs::read_to_string(path)?),
         })
     }
 
     /// Create a new source file from memory.
     pub fn from_memory(code: Cow<'static, str>) -> Self {
-        Self { name: Cow::Borrowed("--"), code }
+        Self { name: Cow::Borrowed("--"), code, path: None }
     }
 
     /// Get the name of the source file.
     pub fn name(&self) -> &str {
         &self.name
     }
+
+    /// Get the name of the module. If the source code doesn't have a valid name (e.g. it doesn't
+    /// end in ".vvs"), returns [None].
+    pub fn module(&self) -> Option<&str> {
+        self.name().strip_suffix(VIVY_SCRIPT_EXTENSION)?.strip_suffix('.')
+    }
+
+    /// Gets the parent folder of the script if it exists.
+    pub fn folder(&self) -> Option<&Path> {
+        self.path.as_deref()
+    }
 }