diff --git a/src/Rust/Cargo.lock b/src/Rust/Cargo.lock
index 79912599051150568032984aec0e5c18cda8bf13..9f75e1e998856296c98bf40ef8ef5b9bf9073b9c 100644
--- a/src/Rust/Cargo.lock
+++ b/src/Rust/Cargo.lock
@@ -106,6 +106,15 @@ version = "1.0.86"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da"
 
+[[package]]
+name = "approx"
+version = "0.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cab112f0a86d568ea0e627cc1d6be74a1e9cd55214684db5561995f6dad897c6"
+dependencies = [
+ "num-traits",
+]
+
 [[package]]
 name = "autocfg"
 version = "1.3.0"
@@ -143,18 +152,39 @@ version = "3.16.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c"
 
+[[package]]
+name = "by_address"
+version = "1.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "64fa3c856b712db6612c019f14756e64e4bcea13337a6b33b696333a9eaa2d06"
+
 [[package]]
 name = "bytecount"
 version = "0.6.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "5ce89b21cab1437276d2650d57e971f9d548a2d9037cc231abdc0562b97498ce"
 
+[[package]]
+name = "cassowary"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "df8670b8c7b9dae1793364eafadf7239c40d669904660c5960d74cfd80b46a53"
+
 [[package]]
 name = "cast"
 version = "0.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5"
 
+[[package]]
+name = "castaway"
+version = "0.2.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0abae9be0aaf9ea96a3b1b8b1b55c602ca751eba1b1500220cea4ecbafe7c0d5"
+dependencies = [
+ "rustversion",
+]
+
 [[package]]
 name = "cbindgen"
 version = "0.27.0"
@@ -307,6 +337,20 @@ version = "1.0.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "d3fd119d74b830634cea2a0f58bbd0d54540518a14397557951e79340abc28c0"
 
+[[package]]
+name = "compact_str"
+version = "0.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6050c3a16ddab2e412160b31f2c871015704239bca62f72f6e5f0be631d3f644"
+dependencies = [
+ "castaway",
+ "cfg-if",
+ "itoa",
+ "rustversion",
+ "ryu",
+ "static_assertions",
+]
+
 [[package]]
 name = "console"
 version = "0.15.8"
@@ -340,7 +384,7 @@ dependencies = [
  "clap",
  "criterion-plot",
  "is-terminal",
- "itertools",
+ "itertools 0.10.5",
  "num-traits",
  "once_cell",
  "oorandom",
@@ -361,7 +405,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "6b50826342786a51a89e2da3a28f1c32b06e387201bc2d19791f622c673706b1"
 dependencies = [
  "cast",
- "itertools",
+ "itertools 0.10.5",
 ]
 
 [[package]]
@@ -389,6 +433,31 @@ version = "0.8.20"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80"
 
+[[package]]
+name = "crossterm"
+version = "0.28.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "829d955a0bb380ef178a640b91779e3987da38c9aea133b20614cfed8cdea9c6"
+dependencies = [
+ "bitflags",
+ "crossterm_winapi",
+ "mio",
+ "parking_lot",
+ "rustix",
+ "signal-hook",
+ "signal-hook-mio",
+ "winapi",
+]
+
+[[package]]
+name = "crossterm_winapi"
+version = "0.9.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "acdd7c62a3665c7f6830a51635d9ac9b23ed385797f70a83bb8bafe9c572ab2b"
+dependencies = [
+ "winapi",
+]
+
 [[package]]
 name = "crunchy"
 version = "0.2.2"
@@ -445,6 +514,12 @@ dependencies = [
  "windows-sys 0.52.0",
 ]
 
+[[package]]
+name = "fast-srgb8"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dd2e7510819d6fbf51a5545c8f922716ecfb14df168a3242f7d33e0239efe6a1"
+
 [[package]]
 name = "fastrand"
 version = "2.1.1"
@@ -496,6 +571,12 @@ version = "0.5.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
 
+[[package]]
+name = "hermit-abi"
+version = "0.3.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024"
+
 [[package]]
 name = "hermit-abi"
 version = "0.4.0"
@@ -527,13 +608,23 @@ dependencies = [
  "walkdir",
 ]
 
+[[package]]
+name = "instability"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b23a0c8dfe501baac4adf6ebbfa6eddf8f0c07f56b058cc1288017e32397846c"
+dependencies = [
+ "quote",
+ "syn 2.0.77",
+]
+
 [[package]]
 name = "is-terminal"
 version = "0.4.13"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "261f68e344040fbd0edea105bef17c66edf46f984ddb1115b775ce31be948f4b"
 dependencies = [
- "hermit-abi",
+ "hermit-abi 0.4.0",
  "libc",
  "windows-sys 0.52.0",
 ]
@@ -553,6 +644,15 @@ dependencies = [
  "either",
 ]
 
+[[package]]
+name = "itertools"
+version = "0.13.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186"
+dependencies = [
+ "either",
+]
+
 [[package]]
 name = "itoa"
 version = "1.0.11"
@@ -606,18 +706,50 @@ dependencies = [
  "semver",
 ]
 
+[[package]]
+name = "lock_api"
+version = "0.4.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17"
+dependencies = [
+ "autocfg",
+ "scopeguard",
+]
+
 [[package]]
 name = "log"
 version = "0.4.22"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24"
 
+[[package]]
+name = "lru"
+version = "0.12.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "37ee39891760e7d94734f6f63fedc29a2e4a152f836120753a72503f09fcf904"
+dependencies = [
+ "hashbrown",
+]
+
 [[package]]
 name = "memchr"
 version = "2.7.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
 
+[[package]]
+name = "mio"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec"
+dependencies = [
+ "hermit-abi 0.3.9",
+ "libc",
+ "log",
+ "wasi",
+ "windows-sys 0.52.0",
+]
+
 [[package]]
 name = "num-traits"
 version = "0.2.19"
@@ -648,12 +780,101 @@ dependencies = [
  "ttf-parser",
 ]
 
+[[package]]
+name = "palette"
+version = "0.7.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4cbf71184cc5ecc2e4e1baccdb21026c20e5fc3dcf63028a086131b3ab00b6e6"
+dependencies = [
+ "approx",
+ "fast-srgb8",
+ "palette_derive",
+ "phf",
+]
+
+[[package]]
+name = "palette_derive"
+version = "0.7.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f5030daf005bface118c096f510ffb781fc28f9ab6a32ab224d8631be6851d30"
+dependencies = [
+ "by_address",
+ "proc-macro2",
+ "quote",
+ "syn 2.0.77",
+]
+
+[[package]]
+name = "parking_lot"
+version = "0.12.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27"
+dependencies = [
+ "lock_api",
+ "parking_lot_core",
+]
+
+[[package]]
+name = "parking_lot_core"
+version = "0.9.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8"
+dependencies = [
+ "cfg-if",
+ "libc",
+ "redox_syscall",
+ "smallvec",
+ "windows-targets 0.52.6",
+]
+
 [[package]]
 name = "paste"
 version = "1.0.15"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a"
 
+[[package]]
+name = "phf"
+version = "0.11.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc"
+dependencies = [
+ "phf_macros",
+ "phf_shared",
+]
+
+[[package]]
+name = "phf_generator"
+version = "0.11.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "48e4cc64c2ad9ebe670cb8fd69dd50ae301650392e81c05f9bfcb2d5bdbc24b0"
+dependencies = [
+ "phf_shared",
+ "rand",
+]
+
+[[package]]
+name = "phf_macros"
+version = "0.11.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3444646e286606587e49f3bcf1679b8cef1dc2c5ecc29ddacaffc305180d464b"
+dependencies = [
+ "phf_generator",
+ "phf_shared",
+ "proc-macro2",
+ "quote",
+ "syn 2.0.77",
+]
+
+[[package]]
+name = "phf_shared"
+version = "0.11.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "90fcb95eef784c2ac79119d1dd819e162b5da872ce6f3c3abe1e8ca1c082f72b"
+dependencies = [
+ "siphasher",
+]
+
 [[package]]
 name = "plotters"
 version = "0.3.6"
@@ -700,6 +921,43 @@ dependencies = [
  "proc-macro2",
 ]
 
+[[package]]
+name = "rand"
+version = "0.8.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
+dependencies = [
+ "rand_core",
+]
+
+[[package]]
+name = "rand_core"
+version = "0.6.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
+
+[[package]]
+name = "ratatui"
+version = "0.28.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fdef7f9be5c0122f890d58bdf4d964349ba6a6161f705907526d891efabba57d"
+dependencies = [
+ "bitflags",
+ "cassowary",
+ "compact_str",
+ "crossterm",
+ "instability",
+ "itertools 0.13.0",
+ "lru",
+ "palette",
+ "paste",
+ "strum",
+ "strum_macros",
+ "unicode-segmentation",
+ "unicode-truncate",
+ "unicode-width",
+]
+
 [[package]]
 name = "rayon"
 version = "1.10.0"
@@ -720,6 +978,15 @@ dependencies = [
  "crossbeam-utils",
 ]
 
+[[package]]
+name = "redox_syscall"
+version = "0.5.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2a908a6e00f1fdd0dfd9c0eb08ce85126f6d8bbda50017e74bc4a4b7d4a926a4"
+dependencies = [
+ "bitflags",
+]
+
 [[package]]
 name = "regex"
 version = "1.10.6"
@@ -774,6 +1041,12 @@ dependencies = [
  "windows-sys 0.52.0",
 ]
 
+[[package]]
+name = "rustversion"
+version = "1.0.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6"
+
 [[package]]
 name = "ryu"
 version = "1.0.18"
@@ -789,6 +1062,12 @@ dependencies = [
  "winapi-util",
 ]
 
+[[package]]
+name = "scopeguard"
+version = "1.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
+
 [[package]]
 name = "semver"
 version = "1.0.23"
@@ -843,12 +1122,54 @@ version = "1.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
 
+[[package]]
+name = "signal-hook"
+version = "0.3.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8621587d4798caf8eb44879d42e56b9a93ea5dcd315a6487c357130095b62801"
+dependencies = [
+ "libc",
+ "signal-hook-registry",
+]
+
+[[package]]
+name = "signal-hook-mio"
+version = "0.2.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "34db1a06d485c9142248b7a054f034b349b212551f3dfd19c94d45a754a217cd"
+dependencies = [
+ "libc",
+ "mio",
+ "signal-hook",
+]
+
+[[package]]
+name = "signal-hook-registry"
+version = "1.4.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1"
+dependencies = [
+ "libc",
+]
+
 [[package]]
 name = "similar"
 version = "2.6.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "1de1d4f81173b03af4c0cbed3c898f6bff5b870e4a7f5d6f4057d62a7a4b686e"
 
+[[package]]
+name = "siphasher"
+version = "0.3.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d"
+
+[[package]]
+name = "smallvec"
+version = "1.13.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67"
+
 [[package]]
 name = "smol_str"
 version = "0.3.1"
@@ -859,12 +1180,40 @@ dependencies = [
  "serde",
 ]
 
+[[package]]
+name = "static_assertions"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
+
 [[package]]
 name = "strsim"
 version = "0.11.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
 
+[[package]]
+name = "strum"
+version = "0.26.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06"
+dependencies = [
+ "strum_macros",
+]
+
+[[package]]
+name = "strum_macros"
+version = "0.26.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4c6bee85a5a24955dc440386795aa378cd9cf82acd5f764469152d2270e581be"
+dependencies = [
+ "heck 0.5.0",
+ "proc-macro2",
+ "quote",
+ "rustversion",
+ "syn 2.0.77",
+]
+
 [[package]]
 name = "syn"
 version = "1.0.109"
@@ -1001,6 +1350,17 @@ version = "1.11.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202"
 
+[[package]]
+name = "unicode-truncate"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b3644627a5af5fa321c95b9b235a72fd24cd29c648c2c379431e6628655627bf"
+dependencies = [
+ "itertools 0.13.0",
+ "unicode-segmentation",
+ "unicode-width",
+]
+
 [[package]]
 name = "unicode-width"
 version = "0.1.13"
@@ -1048,6 +1408,7 @@ dependencies = [
  "clap_complete",
  "clap_mangen",
  "log",
+ "ratatui",
  "serde",
  "thiserror",
  "toml",
@@ -1173,6 +1534,7 @@ version = "0.5.0"
 dependencies = [
  "anyhow",
  "log",
+ "ratatui",
  "serde",
  "serde_json",
  "vvs_ass",
@@ -1235,6 +1597,12 @@ dependencies = [
  "winapi-util",
 ]
 
+[[package]]
+name = "wasi"
+version = "0.11.0+wasi-snapshot-preview1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
+
 [[package]]
 name = "wasm-bindgen"
 version = "0.2.93"
@@ -1300,6 +1668,22 @@ dependencies = [
  "wasm-bindgen",
 ]
 
+[[package]]
+name = "winapi"
+version = "0.3.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
+dependencies = [
+ "winapi-i686-pc-windows-gnu",
+ "winapi-x86_64-pc-windows-gnu",
+]
+
+[[package]]
+name = "winapi-i686-pc-windows-gnu"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
+
 [[package]]
 name = "winapi-util"
 version = "0.1.9"
@@ -1309,6 +1693,12 @@ dependencies = [
  "windows-sys 0.59.0",
 ]
 
+[[package]]
+name = "winapi-x86_64-pc-windows-gnu"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
+
 [[package]]
 name = "windows-sys"
 version = "0.48.0"
diff --git a/src/Rust/Cargo.toml b/src/Rust/Cargo.toml
index 1bada05b996e61090396cba4abb4be1e24e14722..f5a301a45cedd3a19df9bd09efa7419d5e54168f 100644
--- a/src/Rust/Cargo.toml
+++ b/src/Rust/Cargo.toml
@@ -91,7 +91,8 @@ ttf-parser = { version = "*" }
 ab_glyph   = { version = "*" }
 
 # CLI
-clap_mangen   = "*" # Could be replace by something crafter by hand…
+ratatui       = { version = "*", features = [ "macros", "palette" ] }
+clap_mangen   = "*" # TODO: Could be replace by something crafter by hand…
 clap_complete = "*"
 clap = { version = "*", default-features = false, features = [
     "usage",
diff --git a/src/Rust/vvs_cli/Cargo.toml b/src/Rust/vvs_cli/Cargo.toml
index a83fa5d4aacfeb0bc285ee01864b7d76b5da9c6d..dc91c6da19dc49ef438ef78ab61bf081c117e906 100644
--- a/src/Rust/vvs_cli/Cargo.toml
+++ b/src/Rust/vvs_cli/Cargo.toml
@@ -27,6 +27,7 @@ log.workspace           = true
 clap_mangen.workspace   = true
 clap_complete.workspace = true
 clap.workspace          = true
+ratatui.workspace       = true
 
 [build-dependencies]
 anyhow.workspace = true
diff --git a/src/Rust/vvs_cli/src/args.rs b/src/Rust/vvs_cli/src/args.rs
index 5f74ba2f279764c02b3187e096660c12d14d3839..3b1bd4d71fdcc191100487fde2efa4ff09b560e3 100644
--- a/src/Rust/vvs_cli/src/args.rs
+++ b/src/Rust/vvs_cli/src/args.rs
@@ -1,9 +1,8 @@
 use crate::parser::FileTypeValueParser;
-use clap::Parser;
 use clap_complete::Shell;
 use std::path::PathBuf;
 
-#[derive(Parser, Debug)]
+#[derive(clap::Parser, Debug)]
 #[command( author
          , version
          , about
@@ -11,7 +10,6 @@ use std::path::PathBuf;
          , groups = [ clap::ArgGroup::new("action").args(["manpage", "shell", "font-file", "script.vvs"])
                     , clap::ArgGroup::new("ass")   .args(["subtitle.ass"]).conflicts_with_all(["manpage", "font-file"])
                     , clap::ArgGroup::new("opts")  .args(["options.ini"]) .conflicts_with_all(["shell", "manpage", "font-file"])
-                    , clap::ArgGroup::new("infos") .args(["info"])        .conflicts_with_all(["shell", "manpage", "font-file"])
 ])]
 pub struct Args {
     /// The script to run.
@@ -58,19 +56,6 @@ pub struct Args {
     )]
     pub includes: Vec<PathBuf>,
 
-    /// Shows informations about a script.
-    ///
-    /// The informations consists of the loaded modules, all the options, their possible values,
-    /// the order of the jobs, etc.
-    ///
-    /// When printing informations about a script you won't be able to run it. You can however
-    /// print the informations about a script then enter in iteractive mode.
-    #[arg( short  = 'P'
-         , long   = "info"
-         , action = clap::ArgAction::SetTrue
-    )]
-    pub info: bool,
-
     /// Display infos about embeded fonts or external fonts.
     #[arg( long   = "font-info"
          , action = clap::ArgAction::Set
diff --git a/src/Rust/vvs_cli/src/compiler.rs b/src/Rust/vvs_cli/src/compiler.rs
new file mode 100644
index 0000000000000000000000000000000000000000..9fafdcc60a5912a417007b9dc4ce30ccf704ab12
--- /dev/null
+++ b/src/Rust/vvs_cli/src/compiler.rs
@@ -0,0 +1,48 @@
+use crate::args::Args;
+use anyhow::Context as _;
+use clap::CommandFactory as _;
+use std::path::PathBuf;
+use vvs_lang::{FrontendPipeline, SearchPath, SourceCode};
+use vvs_runtime::Runtime;
+use vvs_xdg::file::TempFile;
+
+pub struct Settings {
+    pub script: Option<PathBuf>,
+    pub ass_file: Option<PathBuf>,
+    pub options: Option<PathBuf>,
+    pub includes: Vec<PathBuf>,
+    pub terminal: ratatui::DefaultTerminal,
+}
+
+pub fn run(settings: Settings) -> anyhow::Result<()> {
+    let script = match settings.script {
+        Some(script) => SourceCode::from_path(&script)?,
+        None => return Ok(Args::command().print_help()?),
+    };
+    let _ = script.module().context("expected a valid module name")?;
+
+    let Settings { ass_file, options, includes, .. } = settings;
+    let output = FrontendPipeline::new(&script)
+        .passes(&[])
+        .search(
+            &SearchPath::from_iter(includes)
+                .with_script_folder(script.folder().context("expected the script to have a parent folder")?),
+        )
+        .options(options.as_ref())?
+        .run()?;
+
+    let mut file = TempFile::new("vvcc")?;
+    Runtime::new(move |ctx| {
+        Ok(vvs_codegen::lowerer::Lowerer::new(&ctx, &output.main.name)?
+            .declare_globals(output.declared_functions())?
+            .lower_module(&output.main.name, output.ast)?
+            .lower_modules(output.imports)?
+            .generate_main(output.main)?
+            .finished())
+    })?
+    .with_output_file(&mut file)
+    .with_terminal(settings.terminal)
+    .run_on_file(ass_file.context("no subtitle file to run the script on")?)?;
+    file.leak();
+    Ok(())
+}
diff --git a/src/Rust/vvs_cli/src/config.rs b/src/Rust/vvs_cli/src/config.rs
index 25772ae6c976df7ded339d3161dccaa2ded71c4c..026ea26ff9770134993d857cc44b97727a989004 100644
--- a/src/Rust/vvs_cli/src/config.rs
+++ b/src/Rust/vvs_cli/src/config.rs
@@ -29,7 +29,6 @@ pub struct Config {
     pub script: Option<PathBuf>,
     pub ass_file: Option<PathBuf>,
     pub options: Option<PathBuf>,
-    pub info: bool,
     pub manpage: bool,
     pub shell: Option<Shell>,
     pub font_info: Option<Option<PathBuf>>,
@@ -114,7 +113,7 @@ impl Config {
             append     args => self, { includes };
             set_if_not args => self, { script, ass_file, options, shell, font_info };
             max        args => self, { verbose };
-            override   args => self, { info, manpage };
+            override   args => self, { manpage };
         }
         self
     }
diff --git a/src/Rust/vvs_cli/src/lib.rs b/src/Rust/vvs_cli/src/lib.rs
index 2c31f840f0a5cd4c6123589fe9f2dbfc68920392..784888b9061a17bd12603b6f5fff89f5d349ef23 100644
--- a/src/Rust/vvs_cli/src/lib.rs
+++ b/src/Rust/vvs_cli/src/lib.rs
@@ -1,6 +1,7 @@
 #![forbid(unsafe_code)]
 
 pub mod args;
+pub mod compiler;
 pub mod config;
 pub mod logger;
 
diff --git a/src/Rust/vvs_cli/src/main.rs b/src/Rust/vvs_cli/src/main.rs
index c8030eca5a55488bcfd5c52fc8d87096ac55f166..ddf5ca0dbcf9870a04a60f1da517bc7bdf417529 100644
--- a/src/Rust/vvs_cli/src/main.rs
+++ b/src/Rust/vvs_cli/src/main.rs
@@ -7,11 +7,10 @@ use clap::{CommandFactory as _, Parser as _};
 use std::{fs, io, path::Path};
 use vvs_cli::{
     args::Args,
+    compiler,
     config::{Config, ConfigFile},
 };
-use vvs_lang::{FrontendPipeline, SearchPath, SourceCode};
-use vvs_runtime::Runtime;
-use vvs_xdg::{file::TempFile, XDGConfig, XDGConfigMergedSilent};
+use vvs_xdg::{XDGConfig, XDGConfigMergedSilent};
 
 fn print_font(n: impl AsRef<Path>, f: &[u8]) -> Result<()> {
     let f = vvs_font::Font::try_from(f).with_context(|| format!("failed to parse font {}", n.as_ref().display()))?;
@@ -27,7 +26,7 @@ fn print_font(n: impl AsRef<Path>, f: &[u8]) -> Result<()> {
 fn main() -> Result<()> {
     vvs_cli::logger::init(None).context("failed to init logger")?;
 
-    let Config { script, ass_file, options, info, manpage, shell, font_info, includes, .. } = Config::default()
+    let Config { script, ass_file, options, manpage, shell, font_info, includes, .. } = Config::default()
         .with_config_file(
             XDGConfig::<ConfigFile, XDGConfigMergedSilent>::new("vvcc")
                 .file("vvcc.toml")
@@ -36,60 +35,21 @@ fn main() -> Result<()> {
         .with_args(Args::parse())
         .apply_logger();
 
-    // Handle auxiliary stuff
     if manpage {
-        return clap_mangen::Man::new(Args::command())
+        clap_mangen::Man::new(Args::command())
             .render(&mut io::stdout())
-            .context("failed to render manpage for vvcc");
+            .context("failed to render manpage for vvcc")
     } else if let Some(shell) = shell {
         clap_complete::generate(shell, &mut Args::command(), Args::command().get_name().to_string(), &mut io::stdout());
-        return Ok(());
+        Ok(())
     } else if let Some(font_info) = font_info {
-        return match font_info {
+        match font_info {
             Some(p) => print_font(&p, &fs::read(&p).with_context(|| format!("failed to read font: {}", p.display()))?),
             None => vvs_font::embeded_fonts().try_for_each(|(n, f)| print_font(n, f)),
-        };
-    }
-
-    // Parse, build, execute the script.
-    let script = match script {
-        Some(script) => SourceCode::from_path(&script)?,
-        None => return Ok(Args::command().print_help()?),
-    };
-    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.folder().context("expected the script to have a parent folder")?),
-        )
-        .options(options.as_ref())?
-        .run()?;
-
-    if info {
-        match ass_file {
-            Some(ref path) => println!("ass file ........... {}", path.display()),
-            None => println!("ass file ........... ø"),
         }
-        match options {
-            Some(path) => println!("options file ....... {}", path.display()),
-            None => println!("options file ....... ø"),
-        }
-        print!("{output}");
+    } else {
+        compiler::run(compiler::Settings { script, ass_file, options, includes, terminal: ratatui::init() })?;
+        ratatui::restore();
+        Ok(())
     }
-
-    let mut file = TempFile::new("vvcc")?;
-    Runtime::new(move |ctx| {
-        Ok(vvs_codegen::lowerer::Lowerer::new(&ctx, &output.main.name)?
-            .declare_globals(output.declared_functions())?
-            .lower_module(&output.main.name, output.ast)?
-            .lower_modules(output.imports)?
-            .generate_main(output.main)?
-            .finished())
-    })?
-    .run_on_file(ass_file.context("no subtitle file to run the script on")?)?
-    .write_ass_to_file(&mut file)?;
-
-    println!("output file ........ {}", file.leak().path().display());
-    Ok(())
 }
diff --git a/src/Rust/vvs_runtime/Cargo.toml b/src/Rust/vvs_runtime/Cargo.toml
index 25ee18213b4bcfc88847c914a5f978fed636b285..40e2e94761c08ff7c9f26de1c653fb389a772d8b 100644
--- a/src/Rust/vvs_runtime/Cargo.toml
+++ b/src/Rust/vvs_runtime/Cargo.toml
@@ -11,6 +11,7 @@ log.workspace               = true
 anyhow.workspace            = true
 serde.workspace             = true
 serde_json.workspace        = true
+ratatui.workspace           = true
 vvs_runtime_types.workspace = true
 vvs_ass.workspace           = true
 vvs_utils.workspace         = true
diff --git a/src/Rust/vvs_runtime/src/runtime.rs b/src/Rust/vvs_runtime/src/runtime.rs
index 3eb25e53ab62ef56d3b6baa27a710b8aacbbf49b..a1b65e9c996c69ff9f466c38d0b8276527d19f7a 100644
--- a/src/Rust/vvs_runtime/src/runtime.rs
+++ b/src/Rust/vvs_runtime/src/runtime.rs
@@ -1,28 +1,30 @@
 use crate::workers::Workers;
 use anyhow::{bail, Context as _};
-use std::{
-    path::Path,
-    sync::{
-        atomic::{AtomicU64, Ordering},
-        Arc,
-    },
-    thread,
-};
+use std::{fs, path::Path, sync::atomic::Ordering, thread};
 use vvs_ass::{ass_container_from_file, ASSContainer};
 use vvs_llvm::prelude::*;
 use vvs_runtime_types::types::VVRTTable;
 
+use ratatui::{
+    crossterm::event::{self, Event, KeyCode, KeyEventKind},
+    widgets::{Block, Paragraph},
+};
+
 #[allow(dead_code)]
-pub struct Runtime {
+pub struct Runtime<'a> {
     jit: JIT,
     workers: Workers,
+    output: Option<&'a mut fs::File>,
+    terminal: Option<ratatui::DefaultTerminal>,
 }
 
-impl Runtime {
-    pub fn new<'a>(init: impl FnOnce(Context<'a>) -> anyhow::Result<Module<'a>>) -> anyhow::Result<Self> {
+impl<'a> Runtime<'a> {
+    pub fn new<'ctx>(init: impl FnOnce(Context<'ctx>) -> anyhow::Result<Module<'ctx>>) -> anyhow::Result<Self> {
         Ok(Self {
             jit: JIT::init(init)?,
-            workers: Workers::new(|flag: Arc<AtomicU64>| loop {
+            output: None,
+            terminal: None,
+            workers: Workers::new(|flag| loop {
                 match flag.load(Ordering::SeqCst) {
                     0 => thread::yield_now(),
                     u64::MAX => return Ok(()),
@@ -32,13 +34,45 @@ impl Runtime {
         })
     }
 
-    pub fn run_on_container(self, ass: ASSContainer<VVRTTable>) -> anyhow::Result<ASSContainer<VVRTTable>> {
-        todo!("run on {ass:?}")
+    pub fn with_output_file(self, output: &'a mut fs::File) -> Self {
+        Self { output: Some(output), ..self }
     }
 
-    pub fn run_on_file(self, file: impl AsRef<Path>) -> anyhow::Result<ASSContainer<VVRTTable>> {
+    pub fn with_terminal(self, terminal: ratatui::DefaultTerminal) -> Self {
+        Self { terminal: Some(terminal), ..self }
+    }
+
+    pub fn run_on_file(self, file: impl AsRef<Path>) -> anyhow::Result<()> {
         self.run_on_container(
             ass_container_from_file::<VVRTTable>(file.as_ref()).context("failed to parse the subtitle file")?,
         )
     }
+
+    pub fn run_on_container(self, ass: ASSContainer<VVRTTable>) -> anyhow::Result<()> {
+        let Self { output, terminal, .. } = self;
+        log::error!("run on {ass:?}");
+
+        match terminal {
+            None => todo!("handle the case where we don't have a terminal"),
+            Some(mut terminal) => loop {
+                terminal.draw(|frame| {
+                    frame.render_widget(
+                        Paragraph::new("Hello World!").block(Block::bordered().title("Greeting")),
+                        frame.area(),
+                    );
+                })?;
+                if let Event::Key(key) = event::read()? {
+                    if key.kind == KeyEventKind::Press && key.code == KeyCode::Char('q') {
+                        break;
+                    }
+                }
+            },
+        }
+
+        if let Some(output) = output {
+            ass.write_ass_to_file(output)?;
+        }
+
+        Ok(())
+    }
 }
diff --git a/src/Rust/vvs_xdg/src/file/temp.rs b/src/Rust/vvs_xdg/src/file/temp.rs
index 3481602447d8604596b53e199482b4f165a3884d..38360a1e70e2d77a2d02c3fb60c1c1ab530bae32 100644
--- a/src/Rust/vvs_xdg/src/file/temp.rs
+++ b/src/Rust/vvs_xdg/src/file/temp.rs
@@ -49,6 +49,18 @@ impl DerefMut for TempFile {
     }
 }
 
+impl AsRef<File> for TempFile {
+    fn as_ref(&self) -> &File {
+        self.deref()
+    }
+}
+
+impl AsMut<File> for TempFile {
+    fn as_mut(&mut self) -> &mut File {
+        self.deref_mut()
+    }
+}
+
 impl Drop for TempFile {
     fn drop(&mut self) {
         if !self.leak {