diff --git a/Cargo.lock b/Cargo.lock
index 809b5c32615065be4ab590a971485cb69fe0a194..63fe972722fc3020aa0a217777418d246257b9ce 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -80,6 +80,18 @@ dependencies = [
  "windows-sys 0.52.0",
 ]
 
+[[package]]
+name = "arpist"
+version = "0.1.0"
+dependencies = [
+ "clap",
+ "csv",
+ "log",
+ "serde",
+ "serialport",
+ "simple_logger",
+]
+
 [[package]]
 name = "bitflags"
 version = "1.3.2"
@@ -105,6 +117,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "bfaff671f6b22ca62406885ece523383b9b64022e341e53e009a62ebc47a45f2"
 dependencies = [
  "clap_builder",
+ "clap_derive",
 ]
 
 [[package]]
@@ -119,6 +132,18 @@ dependencies = [
  "strsim",
 ]
 
+[[package]]
+name = "clap_derive"
+version = "4.4.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cf9804afaaf59a91e75b022a30fb7229a7901f60c755489cc61c9b423b836442"
+dependencies = [
+ "heck",
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
 [[package]]
 name = "clap_lex"
 version = "0.6.0"
@@ -171,6 +196,12 @@ dependencies = [
  "powerfmt",
 ]
 
+[[package]]
+name = "heck"
+version = "0.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
+
 [[package]]
 name = "itoa"
 version = "1.0.10"
@@ -350,18 +381,6 @@ dependencies = [
  "syn",
 ]
 
-[[package]]
-name = "serial-middle"
-version = "0.1.0"
-dependencies = [
- "clap",
- "csv",
- "log",
- "serde",
- "serialport",
- "simple_logger",
-]
-
 [[package]]
 name = "serialport"
 version = "4.2.2"
diff --git a/Cargo.toml b/Cargo.toml
index ffdc26d4d82c657ca566d3750ecc9e0e7922250b..d0c0146a507f4c229daca4c6d84e6329b6907b11 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,12 +1,12 @@
 [package]
-name = "serial-middle"
+name = "arpist"
 version = "0.1.0"
 edition = "2021"
 
 # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
 
 [dependencies]
-clap = "4.4.11"
+clap = { version = "4.4.11", features = ["derive"] }
 csv = "1.3.0"
 log = "0.4.20"
 serde = { version = "1.0.193", features = ["derive"] }
diff --git a/README.md b/README.md
index 63d74128284d4b152c5b72b54ff1aeb19e27b013..f8e7d8ec280bb05ffcffaabca3ed7d49ca5ac70b 100644
--- a/README.md
+++ b/README.md
@@ -41,5 +41,9 @@ ARPIST needs a board with a radio module connected to a serial port to work. The
 Once the board has the correct entrypoint flashed, is connected to the serial port and the serial port, you can run ARPIST with the following command:
 
 ```bash
-arpist
+arpist --port <serial_port> <telemetry_file>
 ```
+
+Where `<serial_port>` is the serial port where the board is connected and `<telemetry_file>` is the file containing the telemetry data to send to the board.
+
+**NOTE**: if a single STM32 compatible board is connected to the serial port, ARPIST will automatically detect it and use it, so you can omit the `--port <serial_port>` option.
diff --git a/src/main.rs b/src/main.rs
index 1e3278cc2d823f7640ffdaa97b967db489521318..3669cf94341deff9d0b3bad5583bfaa48f55f0ab 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,15 +1,29 @@
 mod ffi;
 
+use std::fs::File;
 use std::io;
 use std::io::{Read, Write};
+use std::path::PathBuf;
 use std::time::{Duration, Instant};
 
-use ffi::MavlinkPayloadFlightTM;
+use clap::Parser;
 use log::{debug, error, info, trace};
 use serialport::SerialPort;
 
+use ffi::MavlinkPayloadFlightTM;
+
 const EOT: u8 = 0x04;
 
+#[derive(Debug, Parser)]
+struct Cli {
+    /// The serial port to use
+    #[clap(short, long, value_name = "PORT")]
+    port: Option<String>,
+
+    /// The input csv file to read from
+    csv_input: PathBuf,
+}
+
 fn main() {
     simple_logger::SimpleLogger::new()
         .with_level(log::LevelFilter::Info)
@@ -18,11 +32,11 @@ fn main() {
         .init()
         .unwrap();
 
-    let filename = "gemini.csv";
+    let args: Cli = Cli::parse();
     let mut packets = Vec::new();
 
-    info!("reading from {}", filename);
-    let mut rdr = csv::Reader::from_reader(std::fs::File::open(filename).unwrap());
+    info!("reading from {}", args.csv_input.display());
+    let mut rdr = csv::Reader::from_reader(File::open(args.csv_input).unwrap());
     for result in rdr.deserialize() {
         let record: MavlinkPayloadFlightTM = result.unwrap();
         packets.push(record);
@@ -32,15 +46,8 @@ fn main() {
     // convert to packet sequence data structure
     let mut packets = PacketSequence::from(packets);
 
-    // get from args the serial port to use
-    let args: Vec<String> = std::env::args().collect();
-    if args.len() > 2 {
-        println!("Usage: {} <serial port>", args[0]);
-        std::process::exit(1);
-    }
-
     // Open the first serialport available.
-    let port_name = if let Some(port_name) = args.get(1) {
+    let port_name = if let Some(port_name) = args.port {
         port_name.to_owned()
     } else if let Some(p) = get_first_stm32_serial_port() {
         p