Repository: fujiapple852/trippy
Pull request #1190 (2024-06-17 15:47:47)

Trippy API part II


Patch:
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 8bb3425..8b48a0a 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -206,6 +206,8 @@ jobs:
         run: cargo install --git https://github.com/foresterre/cargo-msrv.git cargo-msrv
       - name: check msrv for trippy
         run: cargo msrv verify --output-format json --manifest-path crates/trippy/Cargo.toml -- cargo check
+      - name: check msrv for trippy-tui
+        run: cargo msrv verify --output-format json --manifest-path crates/trippy-tui/Cargo.toml -- cargo check
       - name: check msrv for trippy-core
         run: cargo msrv verify --output-format json --manifest-path crates/trippy-core/Cargo.toml -- cargo check
       - name: check msrv for trippy-packet
diff --git a/Cargo.lock b/Cargo.lock
index d299abf..40c77f1 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -2180,37 +2180,11 @@ name = "trippy"
 version = "0.11.0-dev"
 dependencies = [
  "anyhow",
- "chrono",
- "clap",
- "clap_complete",
- "clap_mangen",
- "comfy-table",
- "crossterm",
- "csv",
- "derive_more",
- "encoding_rs_io",
- "etcetera",
- "humantime",
- "insta",
- "itertools 0.13.0",
- "maxminddb",
- "petgraph",
- "pretty_assertions",
- "ratatui",
- "serde",
- "serde_json",
- "serde_with",
- "serde_yaml",
- "strum",
- "test-case",
- "thiserror",
- "toml",
- "tracing",
- "tracing-chrome",
- "tracing-subscriber",
  "trippy-core",
  "trippy-dns",
+ "trippy-packet",
  "trippy-privilege",
+ "trippy-tui",
 ]
 
 [[package]]
@@ -2281,6 +2255,44 @@ dependencies = [
  "windows-sys 0.52.0",
 ]
 
+[[package]]
+name = "trippy-tui"
+version = "0.11.0-dev"
+dependencies = [
+ "anyhow",
+ "chrono",
+ "clap",
+ "clap_complete",
+ "clap_mangen",
+ "comfy-table",
+ "crossterm",
+ "csv",
+ "derive_more",
+ "encoding_rs_io",
+ "etcetera",
+ "humantime",
+ "insta",
+ "itertools 0.13.0",
+ "maxminddb",
+ "petgraph",
+ "pretty_assertions",
+ "ratatui",
+ "serde",
+ "serde_json",
+ "serde_with",
+ "serde_yaml",
+ "strum",
+ "test-case",
+ "thiserror",
+ "toml",
+ "tracing",
+ "tracing-chrome",
+ "tracing-subscriber",
+ "trippy-core",
+ "trippy-dns",
+ "trippy-privilege",
+]
+
 [[package]]
 name = "tun2"
 version = "2.0.1"
diff --git a/Cargo.toml b/Cargo.toml
index cdd7845..8589723 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,14 @@
 [workspace]
 resolver = "2"
-members = ["crates/trippy", "crates/trippy-core", "crates/trippy-packet", "crates/trippy-privilege", "crates/trippy-dns", "examples/*"]
+members = [
+    "crates/trippy",
+    "crates/trippy-tui",
+    "crates/trippy-core",
+    "crates/trippy-packet",
+    "crates/trippy-privilege",
+    "crates/trippy-dns",
+    "examples/*",
+]
 
 [workspace.package]
 version = "0.11.0-dev"
@@ -12,8 +20,11 @@ readme = "README.md"
 license = "Apache-2.0"
 edition = "2021"
 rust-version = "1.75"
+keywords = ["cli", "tui", "traceroute", "ping", "icmp"]
+categories = ["command-line-utilities", "network-programming"]
 
 [workspace.dependencies]
+trippy-tui = { version = "0.11.0-dev", path = "crates/trippy-tui" }
 trippy-core = { version = "0.11.0-dev", path = "crates/trippy-core" }
 trippy-privilege = { version = "0.11.0-dev", path = "crates/trippy-privilege" }
 trippy-dns = { version = "0.11.0-dev", path = "crates/trippy-dns" }
@@ -27,4 +38,22 @@ tracing = { version = "0.1.40" }
 derive_more = { version = "0.99.18", default-features = false, features = [ "mul", "add", "add_assign" ] }
 test-case = "3.3.1"
 parking_lot = "0.12.3"
-hex-literal = "0.4.1"
\ No newline at end of file
+hex-literal = "0.4.1"
+
+[workspace.lints.rust]
+unsafe_code = "deny"
+rust_2018_idioms = "warn"
+
+[workspace.lints.clippy]
+all = "warn"
+pedantic = { level = "warn", priority = -1 }
+nursery = { level = "warn", priority = -1 }
+module_name_repetitions = "allow"
+struct_field_names = "allow"
+use_self = "allow"
+option_if_let_else = "allow"
+missing_const_for_fn = "allow"
+cast_possible_truncation = "allow"
+missing_errors_doc = "allow"
+cast_precision_loss = "allow"
+cast_sign_loss = "allow"
\ No newline at end of file
diff --git a/Dockerfile b/Dockerfile
index a1d8d5d..5c15e41 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -4,11 +4,13 @@ WORKDIR /app
 COPY Cargo.toml /app
 COPY Cargo.lock /app
 RUN mkdir -p /app/crates/trippy/src
+RUN mkdir -p /app/crates/trippy-tui/src
 RUN mkdir -p /app/crates/trippy-core/src
 RUN mkdir -p /app/crates/trippy-dns/src
 RUN mkdir -p /app/crates/trippy-packet/src
 RUN mkdir -p /app/crates/trippy-privilege/src
 COPY crates/trippy/Cargo.toml /app/crates/trippy/Cargo.toml
+COPY crates/trippy-tui/Cargo.toml /app/crates/trippy-tui/Cargo.toml
 COPY crates/trippy-core/Cargo.toml /app/crates/trippy-core/Cargo.toml
 COPY crates/trippy-dns/Cargo.toml /app/crates/trippy-dns/Cargo.toml
 COPY crates/trippy-packet/Cargo.toml /app/crates/trippy-packet/Cargo.toml
@@ -17,6 +19,7 @@ COPY examples/ /app/examples/
 
 # dummy build to cache dependencies
 RUN echo "fn main() {}" > /app/crates/trippy/src/main.rs
+RUN touch /app/crates/trippy-tui/src/lib.rs
 RUN touch /app/crates/trippy-core/src/lib.rs
 RUN touch /app/crates/trippy-dns/src/lib.rs
 RUN touch /app/crates/trippy-packet/src/lib.rs
@@ -25,13 +28,14 @@ RUN cargo build --release --target=x86_64-unknown-linux-musl --package trippy
 
 # copy the actual application code and build
 COPY crates/trippy/src /app/crates/trippy/src
+COPY crates/trippy-tui/src /app/crates/trippy-tui/src
 COPY crates/trippy-core/src /app/crates/trippy-core/src
 COPY crates/trippy-dns/src /app/crates/trippy-dns/src
 COPY crates/trippy-packet/src /app/crates/trippy-packet/src
 COPY crates/trippy-privilege/src /app/crates/trippy-privilege/src
 COPY trippy-config-sample.toml /app
 COPY README.md /app
-RUN cargo clean --release --target=x86_64-unknown-linux-musl -p trippy-core -p trippy-dns -p trippy-packet -p trippy-privilege
+RUN cargo clean --release --target=x86_64-unknown-linux-musl -p trippy-tui -p trippy-core -p trippy-dns -p trippy-packet -p trippy-privilege
 RUN cargo build --release --target=x86_64-unknown-linux-musl
 
 FROM alpine
diff --git a/crates/README.md b/crates/README.md
index 9f4de99..6ae4c65 100644
--- a/crates/README.md
+++ b/crates/README.md
@@ -45,4 +45,12 @@ may also be useful for other applications.
 
 ```shell
 cargo add trippy-privilege
+```
+
+### `trippy-tui`
+
+A library crate for the Trippy terminal user interface.
+
+```shell
+cargo add trippy-tui
 ```
\ No newline at end of file
diff --git a/crates/trippy-core/Cargo.toml b/crates/trippy-core/Cargo.toml
index 530521a..a81425c 100644
--- a/crates/trippy-core/Cargo.toml
+++ b/crates/trippy-core/Cargo.toml
@@ -10,8 +10,8 @@ readme.workspace = true
 license.workspace = true
 edition.workspace = true
 rust-version.workspace = true
-keywords = ["traceroute", "ping", "icmp"]
-categories = ["network-programming"]
+keywords.workspace = true
+categories.workspace = true
 
 [dependencies]
 trippy-packet.workspace = true
@@ -62,4 +62,7 @@ tun2 = { version = "2.0.1", features = [ "async" ] }
 
 [features]
 # Enable simulation integration tests
-sim-tests = []
\ No newline at end of file
+sim-tests = []
+
+[lints]
+workspace = true
\ No newline at end of file
diff --git a/crates/trippy-core/src/lib.rs b/crates/trippy-core/src/lib.rs
index df115d6..1d11b61 100644
--- a/crates/trippy-core/src/lib.rs
+++ b/crates/trippy-core/src/lib.rs
@@ -54,18 +54,6 @@
 //! - [`Tracer::run_with`] - Run the tracer with a custom round handler.
 //! - [`Tracer::spawn`] - Run the tracer on a new thread.
 //! - [`Tracer::spawn_with`] - Run the tracer on a new thread with a custom round handler.
-#![warn(clippy::all, clippy::pedantic, clippy::nursery, rust_2018_idioms)]
-#![allow(
-    clippy::module_name_repetitions,
-    clippy::struct_field_names,
-    clippy::use_self,
-    clippy::option_if_let_else,
-    clippy::missing_const_for_fn,
-    clippy::cast_possible_truncation,
-    clippy::missing_errors_doc,
-    clippy::cast_precision_loss
-)]
-#![deny(unsafe_code)]
 
 mod builder;
 mod config;
diff --git a/crates/trippy-dns/Cargo.toml b/crates/trippy-dns/Cargo.toml
index 65ea95a..aa26a47 100644
--- a/crates/trippy-dns/Cargo.toml
+++ b/crates/trippy-dns/Cargo.toml
@@ -10,8 +10,8 @@ readme.workspace = true
 license.workspace = true
 edition.workspace = true
 rust-version.workspace = true
-keywords = ["traceroute", "ping", "icmp"]
-categories = ["network-programming"]
+keywords.workspace = true
+categories.workspace = true
 
 [dependencies]
 thiserror.workspace = true
@@ -22,4 +22,7 @@ hickory-resolver = "0.24.1"
 parking_lot.workspace = true
 
 [dev-dependencies]
-anyhow.workspace = true
\ No newline at end of file
+anyhow.workspace = true
+
+[lints]
+workspace = true
\ No newline at end of file
diff --git a/crates/trippy-dns/src/lib.rs b/crates/trippy-dns/src/lib.rs
index 5fb7d5a..3bca1e1 100644
--- a/crates/trippy-dns/src/lib.rs
+++ b/crates/trippy-dns/src/lib.rs
@@ -67,13 +67,6 @@
 //! # Ok(())
 //! # }
 //! ```
-#![warn(clippy::all, clippy::pedantic, clippy::nursery, rust_2018_idioms)]
-#![allow(
-    clippy::module_name_repetitions,
-    clippy::missing_const_for_fn,
-    clippy::missing_errors_doc,
-    clippy::option_if_let_else
-)]
 #![forbid(unsafe_code)]
 
 mod lazy_resolver;
diff --git a/crates/trippy-packet/Cargo.toml b/crates/trippy-packet/Cargo.toml
index b0e8980..2fee01a 100644
--- a/crates/trippy-packet/Cargo.toml
+++ b/crates/trippy-packet/Cargo.toml
@@ -10,8 +10,8 @@ readme.workspace = true
 license.workspace = true
 edition.workspace = true
 rust-version.workspace = true
-keywords = ["traceroute", "ping", "icmp"]
-categories = ["network-programming"]
+keywords.workspace = true
+categories.workspace = true
 
 [dependencies]
 itertools.workspace = true
@@ -19,4 +19,7 @@ thiserror.workspace = true
 
 [dev-dependencies]
 hex-literal.workspace = true
-anyhow.workspace = true
\ No newline at end of file
+anyhow.workspace = true
+
+[lints]
+workspace = true
\ No newline at end of file
diff --git a/crates/trippy-packet/src/lib.rs b/crates/trippy-packet/src/lib.rs
index d68c66b..9454008 100644
--- a/crates/trippy-packet/src/lib.rs
+++ b/crates/trippy-packet/src/lib.rs
@@ -53,15 +53,7 @@
 //! # Ok(())
 //! # }
 //! ```
-#![warn(clippy::all, clippy::pedantic, clippy::nursery, rust_2018_idioms)]
-#![allow(
-    clippy::missing_const_for_fn,
-    clippy::missing_errors_doc,
-    clippy::module_name_repetitions,
-    clippy::cast_possible_truncation,
-    clippy::use_self
-)]
-#![deny(unsafe_code)]
+#![forbid(unsafe_code)]
 
 mod buffer;
 
diff --git a/crates/trippy-privilege/Cargo.toml b/crates/trippy-privilege/Cargo.toml
index a711f6c..ad07328 100644
--- a/crates/trippy-privilege/Cargo.toml
+++ b/crates/trippy-privilege/Cargo.toml
@@ -10,8 +10,8 @@ readme.workspace = true
 license.workspace = true
 edition.workspace = true
 rust-version.workspace = true
-keywords = ["traceroute", "ping", "icmp"]
-categories = ["network-programming"]
+keywords.workspace = true
+categories.workspace = true
 
 [dependencies]
 thiserror.workspace = true
@@ -30,4 +30,7 @@ windows-sys = { version = "0.52.0", features = [
 paste = "1.0.15"
 
 [dev-dependencies]
-anyhow.workspace = true
\ No newline at end of file
+anyhow.workspace = true
+
+[lints]
+workspace = true
\ No newline at end of file
diff --git a/crates/trippy-privilege/src/lib.rs b/crates/trippy-privilege/src/lib.rs
index a419935..e2fad06 100644
--- a/crates/trippy-privilege/src/lib.rs
+++ b/crates/trippy-privilege/src/lib.rs
@@ -81,9 +81,6 @@
 //! # Ok(())
 //! # }
 //! ```
-#![warn(clippy::all, clippy::pedantic, clippy::nursery, rust_2018_idioms)]
-#![allow(clippy::missing_const_for_fn, clippy::missing_errors_doc)]
-#![deny(unsafe_code)]
 
 /// A privilege error result.
 pub type Result<T> = std::result::Result<T, Error>;
diff --git a/crates/trippy-tui/Cargo.toml b/crates/trippy-tui/Cargo.toml
new file mode 100644
index 0000000..805a9ae
--- /dev/null
+++ b/crates/trippy-tui/Cargo.toml
@@ -0,0 +1,58 @@
+[package]
+name = "trippy-tui"
+description = "A network diagnostic tool"
+version.workspace = true
+authors.workspace = true
+documentation.workspace = true
+homepage.workspace = true
+repository.workspace = true
+readme.workspace = true
+license.workspace = true
+edition.workspace = true
+rust-version.workspace = true
+keywords.workspace = true
+categories.workspace = true
+
+[dependencies]
+trippy-core.workspace = true
+trippy-privilege.workspace = true
+trippy-dns.workspace = true
+thiserror.workspace = true
+anyhow.workspace = true
+itertools.workspace = true
+tracing.workspace = true
+serde.workspace = true
+derive_more.workspace = true
+clap = { version = "4.4.0",  default-features = false, features = [ "cargo", "derive", "wrap_help", "usage", "unstable-styles", "color", "suggestions", "error-context" ] }
+clap_complete = "4.4.9"
+humantime = "2.1.0"
+ratatui = "0.27.0"
+crossterm = { version = "0.27.0",  default-features = false, features = [ "events", "windows" ] }
+chrono = { version = "0.4.38", default-features = false, features = [ "clock" ] }
+serde_json = { version = "1.0.117", default-features = false }
+comfy-table = { version = "7.1.0", default-features = false }
+strum = { version = "0.26.3", default-features = false, features = [ "std", "derive" ] }
+etcetera = "0.8.0"
+toml = { version = "0.8.14", default-features = false, features = [ "parse" ] }
+maxminddb = "0.24.0"
+tracing-subscriber = { version = "0.3.18", default-features = false, features = [ "json", "env-filter" ] }
+tracing-chrome = "0.7.2"
+petgraph = "0.6.5"
+csv = "1.3.0"
+serde_with = "3.8.1"
+encoding_rs_io = "0.1.7"
+clap_mangen = "0.2.20"
+
+[dev-dependencies]
+test-case.workspace = true
+serde_yaml.workspace = true
+insta = { version = "1.39.0", features = ["serde"] }
+pretty_assertions = "1.4.0"
+
+[lints]
+workspace = true
+
+[package.metadata.generate-rpm]
+assets = [
+  { source = "target/release/trip", dest = "/usr/bin/trip", mode = "755" },
+]
\ No newline at end of file
diff --git a/crates/trippy/src/app.rs b/crates/trippy-tui/src/app.rs
similarity index 100%
rename from crates/trippy/src/app.rs
rename to crates/trippy-tui/src/app.rs
diff --git a/crates/trippy/src/config.rs b/crates/trippy-tui/src/config.rs
similarity index 100%
rename from crates/trippy/src/config.rs
rename to crates/trippy-tui/src/config.rs
diff --git a/crates/trippy/src/config/binding.rs b/crates/trippy-tui/src/config/binding.rs
similarity index 100%
rename from crates/trippy/src/config/binding.rs
rename to crates/trippy-tui/src/config/binding.rs
diff --git a/crates/trippy/src/config/cmd.rs b/crates/trippy-tui/src/config/cmd.rs
similarity index 100%
rename from crates/trippy/src/config/cmd.rs
rename to crates/trippy-tui/src/config/cmd.rs
diff --git a/crates/trippy/src/config/columns.rs b/crates/trippy-tui/src/config/columns.rs
similarity index 100%
rename from crates/trippy/src/config/columns.rs
rename to crates/trippy-tui/src/config/columns.rs
diff --git a/crates/trippy/src/config/constants.rs b/crates/trippy-tui/src/config/constants.rs
similarity index 100%
rename from crates/trippy/src/config/constants.rs
rename to crates/trippy-tui/src/config/constants.rs
diff --git a/crates/trippy/src/config/file.rs b/crates/trippy-tui/src/config/file.rs
similarity index 100%
rename from crates/trippy/src/config/file.rs
rename to crates/trippy-tui/src/config/file.rs
diff --git a/crates/trippy/src/config/theme.rs b/crates/trippy-tui/src/config/theme.rs
similarity index 100%
rename from crates/trippy/src/config/theme.rs
rename to crates/trippy-tui/src/config/theme.rs
diff --git a/crates/trippy/src/frontend.rs b/crates/trippy-tui/src/frontend.rs
similarity index 99%
rename from crates/trippy/src/frontend.rs
rename to crates/trippy-tui/src/frontend.rs
index 2d425b9..2de572c 100644
--- a/crates/trippy/src/frontend.rs
+++ b/crates/trippy-tui/src/frontend.rs
@@ -55,7 +55,7 @@ pub fn run_frontend(
     Ok(())
 }
 
-#[allow(clippy::too_many_lines)]
+#[allow(clippy::too_many_lines, clippy::cognitive_complexity)]
 fn run_app<B: Backend>(
     terminal: &mut Terminal<B>,
     trace_info: Vec<TraceInfo>,
diff --git a/crates/trippy/src/frontend/binding.rs b/crates/trippy-tui/src/frontend/binding.rs
similarity index 100%
rename from crates/trippy/src/frontend/binding.rs
rename to crates/trippy-tui/src/frontend/binding.rs
diff --git a/crates/trippy/src/frontend/columns.rs b/crates/trippy-tui/src/frontend/columns.rs
similarity index 100%
rename from crates/trippy/src/frontend/columns.rs
rename to crates/trippy-tui/src/frontend/columns.rs
diff --git a/crates/trippy/src/frontend/config.rs b/crates/trippy-tui/src/frontend/config.rs
similarity index 100%
rename from crates/trippy/src/frontend/config.rs
rename to crates/trippy-tui/src/frontend/config.rs
diff --git a/crates/trippy/src/frontend/render.rs b/crates/trippy-tui/src/frontend/render.rs
similarity index 100%
rename from crates/trippy/src/frontend/render.rs
rename to crates/trippy-tui/src/frontend/render.rs
diff --git a/crates/trippy/src/frontend/render/app.rs b/crates/trippy-tui/src/frontend/render/app.rs
similarity index 100%
rename from crates/trippy/src/frontend/render/app.rs
rename to crates/trippy-tui/src/frontend/render/app.rs
diff --git a/crates/trippy/src/frontend/render/body.rs b/crates/trippy-tui/src/frontend/render/body.rs
similarity index 100%
rename from crates/trippy/src/frontend/render/body.rs
rename to crates/trippy-tui/src/frontend/render/body.rs
diff --git a/crates/trippy/src/frontend/render/bsod.rs b/crates/trippy-tui/src/frontend/render/bsod.rs
similarity index 100%
rename from crates/trippy/src/frontend/render/bsod.rs
rename to crates/trippy-tui/src/frontend/render/bsod.rs
diff --git a/crates/trippy/src/frontend/render/chart.rs b/crates/trippy-tui/src/frontend/render/chart.rs
similarity index 100%
rename from crates/trippy/src/frontend/render/chart.rs
rename to crates/trippy-tui/src/frontend/render/chart.rs
diff --git a/crates/trippy/src/frontend/render/flows.rs b/crates/trippy-tui/src/frontend/render/flows.rs
similarity index 100%
rename from crates/trippy/src/frontend/render/flows.rs
rename to crates/trippy-tui/src/frontend/render/flows.rs
diff --git a/crates/trippy/src/frontend/render/footer.rs b/crates/trippy-tui/src/frontend/render/footer.rs
similarity index 100%
rename from crates/trippy/src/frontend/render/footer.rs
rename to crates/trippy-tui/src/frontend/render/footer.rs
diff --git a/crates/trippy/src/frontend/render/header.rs b/crates/trippy-tui/src/frontend/render/header.rs
similarity index 100%
rename from crates/trippy/src/frontend/render/header.rs
rename to crates/trippy-tui/src/frontend/render/header.rs
diff --git a/crates/trippy/src/frontend/render/help.rs b/crates/trippy-tui/src/frontend/render/help.rs
similarity index 100%
rename from crates/trippy/src/frontend/render/help.rs
rename to crates/trippy-tui/src/frontend/render/help.rs
diff --git a/crates/trippy/src/frontend/render/histogram.rs b/crates/trippy-tui/src/frontend/render/histogram.rs
similarity index 100%
rename from crates/trippy/src/frontend/render/histogram.rs
rename to crates/trippy-tui/src/frontend/render/histogram.rs
diff --git a/crates/trippy/src/frontend/render/history.rs b/crates/trippy-tui/src/frontend/render/history.rs
similarity index 100%
rename from crates/trippy/src/frontend/render/history.rs
rename to crates/trippy-tui/src/frontend/render/history.rs
diff --git a/crates/trippy/src/frontend/render/settings.rs b/crates/trippy-tui/src/frontend/render/settings.rs
similarity index 100%
rename from crates/trippy/src/frontend/render/settings.rs
rename to crates/trippy-tui/src/frontend/render/settings.rs
diff --git a/crates/trippy/src/frontend/render/splash.rs b/crates/trippy-tui/src/frontend/render/splash.rs
similarity index 100%
rename from crates/trippy/src/frontend/render/splash.rs
rename to crates/trippy-tui/src/frontend/render/splash.rs
diff --git a/crates/trippy/src/frontend/render/table.rs b/crates/trippy-tui/src/frontend/render/table.rs
similarity index 99%
rename from crates/trippy/src/frontend/render/table.rs
rename to crates/trippy-tui/src/frontend/render/table.rs
index aa85b2f..3d44fa4 100644
--- a/crates/trippy/src/frontend/render/table.rs
+++ b/crates/trippy-tui/src/frontend/render/table.rs
@@ -564,7 +564,7 @@ fn format_details(
 ///
 /// Format as follows:
 ///
-/// ```
+/// ```text
 /// 172.217.24.78 [1 of 2]
 /// Host: hkg07s50-in-f14.1e100.net
 /// AS Name: AS15169 GOOGLE, US
diff --git a/crates/trippy/src/frontend/render/tabs.rs b/crates/trippy-tui/src/frontend/render/tabs.rs
similarity index 100%
rename from crates/trippy/src/frontend/render/tabs.rs
rename to crates/trippy-tui/src/frontend/render/tabs.rs
diff --git a/crates/trippy/src/frontend/render/util.rs b/crates/trippy-tui/src/frontend/render/util.rs
similarity index 100%
rename from crates/trippy/src/frontend/render/util.rs
rename to crates/trippy-tui/src/frontend/render/util.rs
diff --git a/crates/trippy/src/frontend/render/world.rs b/crates/trippy-tui/src/frontend/render/world.rs
similarity index 100%
rename from crates/trippy/src/frontend/render/world.rs
rename to crates/trippy-tui/src/frontend/render/world.rs
diff --git a/crates/trippy/src/frontend/theme.rs b/crates/trippy-tui/src/frontend/theme.rs
similarity index 100%
rename from crates/trippy/src/frontend/theme.rs
rename to crates/trippy-tui/src/frontend/theme.rs
diff --git a/crates/trippy/src/frontend/tui_app.rs b/crates/trippy-tui/src/frontend/tui_app.rs
similarity index 100%
rename from crates/trippy/src/frontend/tui_app.rs
rename to crates/trippy-tui/src/frontend/tui_app.rs
diff --git a/crates/trippy/src/geoip.rs b/crates/trippy-tui/src/geoip.rs
similarity index 100%
rename from crates/trippy/src/geoip.rs
rename to crates/trippy-tui/src/geoip.rs
diff --git a/crates/trippy-tui/src/lib.rs b/crates/trippy-tui/src/lib.rs
new file mode 100644
index 0000000..d7907cc
--- /dev/null
+++ b/crates/trippy-tui/src/lib.rs
@@ -0,0 +1,32 @@
+#![allow(clippy::struct_excessive_bools)]
+#![forbid(unsafe_code)]
+
+use crate::config::TrippyAction;
+use clap::Parser;
+use config::Args;
+use std::process;
+use trippy_privilege::Privilege;
+
+mod app;
+mod config;
+mod frontend;
+mod geoip;
+mod print;
+mod report;
+mod util;
+
+/// Run the Trippy application.
+pub fn trippy() -> anyhow::Result<()> {
+    let args = Args::parse();
+    let privilege = Privilege::acquire_privileges()?;
+    let pid = u16::try_from(process::id() % u32::from(u16::MAX))?;
+    match TrippyAction::from(args, &privilege, pid)? {
+        TrippyAction::Trippy(cfg) => app::run_trippy(&cfg, pid)?,
+        TrippyAction::PrintTuiThemeItems => print::print_tui_theme_items(),
+        TrippyAction::PrintTuiBindingCommands => print::print_tui_binding_commands(),
+        TrippyAction::PrintConfigTemplate => print::print_config_template(),
+        TrippyAction::PrintManPage => print::print_man_page()?,
+        TrippyAction::PrintShellCompletions(shell) => print::print_shell_completions(shell)?,
+    }
+    Ok(())
+}
diff --git a/crates/trippy/Cargo.toml b/crates/trippy/Cargo.toml
index ef39c29..65f5dcb 100644
--- a/crates/trippy/Cargo.toml
+++ b/crates/trippy/Cargo.toml
@@ -10,51 +10,29 @@ readme.workspace = true
 license.workspace = true
 edition.workspace = true
 rust-version.workspace = true
-keywords = ["cli", "tui", "traceroute", "ping", "icmp"]
-categories = ["command-line-utilities", "network-programming"]
+keywords.workspace = true
+categories.workspace = true
 
 [[bin]]
-bench = false
-path = "src/main.rs"
 name = "trip"
+path = "src/main.rs"
+required-features = [ "tui" ]
 
-[dependencies]
-trippy-core.workspace = true
-trippy-privilege.workspace = true
-trippy-dns.workspace = true
-thiserror.workspace = true
-anyhow.workspace = true
-itertools.workspace = true
-tracing.workspace = true
-serde.workspace = true
-derive_more.workspace = true
-clap = { version = "4.4.0",  default-features = false, features = [ "cargo", "derive", "wrap_help", "usage", "unstable-styles", "color", "suggestions", "error-context" ] }
-clap_complete = "4.4.9"
-humantime = "2.1.0"
-ratatui = "0.27.0"
-crossterm = { version = "0.27.0",  default-features = false, features = [ "events", "windows" ] }
-chrono = { version = "0.4.38", default-features = false, features = [ "clock" ] }
-serde_json = { version = "1.0.117", default-features = false }
-comfy-table = { version = "7.1.0", default-features = false }
-strum = { version = "0.26.3", default-features = false, features = [ "std", "derive" ] }
-etcetera = "0.8.0"
-toml = { version = "0.8.14", default-features = false, features = [ "parse" ] }
-maxminddb = "0.24.0"
-tracing-subscriber = { version = "0.3.18", default-features = false, features = [ "json", "env-filter" ] }
-tracing-chrome = "0.7.2"
-petgraph = "0.6.5"
-csv = "1.3.0"
-serde_with = "3.8.1"
-encoding_rs_io = "0.1.7"
-clap_mangen = "0.2.20"
+[features]
+default = [ "tui" ]
+tui = [ "trippy-tui", "anyhow" ]
+core = [ "trippy-core" ]
+privilege = [ "trippy-privilege" ]
+dns = [ "trippy-dns" ]
+packet = [ "trippy-packet" ]
 
-[dev-dependencies]
-test-case.workspace = true
-serde_yaml.workspace = true
-insta = { version = "1.39.0", features = ["serde"] }
-pretty_assertions = "1.4.0"
+[dependencies]
+trippy-tui = { workspace = true, optional = true }
+trippy-core = { workspace = true, optional = true }
+trippy-privilege = { workspace = true, optional = true }
+trippy-dns = { workspace = true, optional = true }
+trippy-packet = { workspace = true, optional = true }
+anyhow = { workspace = true, optional = true }
 
-[package.metadata.generate-rpm]
-assets = [
-  { source = "target/release/trip", dest = "/usr/bin/trip", mode = "755" },
-]
+[lints]
+workspace = true
\ No newline at end of file
diff --git a/crates/trippy/src/lib.rs b/crates/trippy/src/lib.rs
index 457f975..ca140ea 100644
--- a/crates/trippy/src/lib.rs
+++ b/crates/trippy/src/lib.rs
@@ -1,19 +1,32 @@
-#![allow(rustdoc::broken_intra_doc_links, rustdoc::bare_urls)]
+#![allow(
+    rustdoc::broken_intra_doc_links,
+    rustdoc::bare_urls,
+    clippy::doc_markdown
+)]
 #![doc = include_str!("../../../README.md")]
 
 // Re-export the user facing libraries, so they may be used from trippy crate directly.
 
+#[cfg(feature = "core")]
 /// A network tracer.
 pub mod core {
     pub use trippy_core::*;
 }
 
+#[cfg(feature = "dns")]
 /// A lazy DNS resolver.
 pub mod dns {
     pub use trippy_dns::*;
 }
 
+#[cfg(feature = "privilege")]
 /// Discover platform privileges.
 pub mod privilege {
     pub use trippy_privilege::*;
 }
+
+#[cfg(feature = "packet")]
+/// Network packets.
+pub mod packet {
+    pub use trippy_packet::*;
+}
diff --git a/crates/trippy/src/main.rs b/crates/trippy/src/main.rs
index 43452b1..06eab58 100644
--- a/crates/trippy/src/main.rs
+++ b/crates/trippy/src/main.rs
@@ -1,45 +1,3 @@
-#![warn(clippy::all, clippy::pedantic, clippy::nursery, rust_2018_idioms)]
-#![allow(
-    clippy::module_name_repetitions,
-    clippy::redundant_field_names,
-    clippy::struct_field_names,
-    clippy::option_if_let_else,
-    clippy::missing_const_for_fn,
-    clippy::cast_precision_loss,
-    clippy::cast_sign_loss,
-    clippy::cast_possible_truncation,
-    clippy::redundant_pub_crate,
-    clippy::struct_excessive_bools,
-    clippy::cognitive_complexity,
-    clippy::option_option
-)]
-#![forbid(unsafe_code)]
-
-use crate::config::TrippyAction;
-use clap::Parser;
-use config::Args;
-use std::process;
-use trippy_privilege::Privilege;
-
-mod app;
-mod config;
-mod frontend;
-mod geoip;
-mod print;
-mod report;
-mod util;
-
 fn main() -> anyhow::Result<()> {
-    let args = Args::parse();
-    let privilege = Privilege::acquire_privileges()?;
-    let pid = u16::try_from(process::id() % u32::from(u16::MAX))?;
-    match TrippyAction::from(args, &privilege, pid)? {
-        TrippyAction::Trippy(cfg) => app::run_trippy(&cfg, pid)?,
-        TrippyAction::PrintTuiThemeItems => print::print_tui_theme_items(),
-        TrippyAction::PrintTuiBindingCommands => print::print_tui_binding_commands(),
-        TrippyAction::PrintConfigTemplate => print::print_config_template(),
-        TrippyAction::PrintManPage => print::print_man_page()?,
-        TrippyAction::PrintShellCompletions(shell) => print::print_shell_completions(shell)?,
-    }
-    Ok(())
+    trippy_tui::trippy()
 }
diff --git a/examples/hello-world/Cargo.toml b/examples/hello-world/Cargo.toml
index 9f5223b..04de14a 100644
--- a/examples/hello-world/Cargo.toml
+++ b/examples/hello-world/Cargo.toml
@@ -6,5 +6,5 @@ edition = "2021"
 rust-version = "1.75"
 
 [dependencies]
-trippy = { version = "0.11.0-dev", path = "../../crates/trippy" }
+trippy = { version = "0.11.0-dev", path = "../../crates/trippy", default-features = false, features = [ "core" ] }
 anyhow = "1.0.86"
\ No newline at end of file
diff --git a/examples/traceroute/Cargo.toml b/examples/traceroute/Cargo.toml
index 7b7fc76..d522489 100644
--- a/examples/traceroute/Cargo.toml
+++ b/examples/traceroute/Cargo.toml
@@ -6,7 +6,7 @@ edition = "2021"
 rust-version = "1.75"
 
 [dependencies]
-trippy = { version = "0.11.0-dev", path = "../../crates/trippy" }
+trippy = { version = "0.11.0-dev", path = "../../crates/trippy", default-features = false, features = [ "core", "dns" ] }
 anyhow = "1.0.86"
 itertools = "0.13.0"
-clap = "4.5.7"
\ No newline at end of file
+clap = { version = "4.5.7", features = [ "derive" ] }
\ No newline at end of file


Test patch:
diff --git a/crates/trippy-core/tests/sim/network.rs b/crates/trippy-core/tests/sim/network.rs
index 3b8c264..8a52fd2 100644
--- a/crates/trippy-core/tests/sim/network.rs
+++ b/crates/trippy-core/tests/sim/network.rs
@@ -21,6 +21,7 @@ use trippy_packet::IpProtocol;
 
 const READ_TIMEOUT: Duration = Duration::from_millis(10);
 
+#[allow(clippy::too_many_lines)]
 pub async fn run(
     tun: Arc<Mutex<TunDevice>>,
     sim: Arc<Simulation>,
@@ -32,7 +33,7 @@ pub async fn run(
         let bytes_read = {
             let tun = tun.clone();
             tokio::select!(
-                _ = token.cancelled() => {
+                () = token.cancelled() => {
                     handles.into_iter().for_each(|h| h.abort());
                     return Ok(())
                 },
@@ -108,7 +109,7 @@ pub async fn run(
                 addr: IpAddr::V4(addr),
                 rtt_ms,
             }) => (addr, rtt_ms),
-            _ => unimplemented!(),
+            Response::SingleHost(_) => unimplemented!(),
         };
 
         // decide what response to send
@@ -195,10 +196,9 @@ pub async fn run(
             let tun = tun.clone();
             tokio::spawn(async move {
                 tokio::time::sleep(Duration::from_millis(u64::from(reply_delay_ms))).await;
-                let mut tun = tun.lock().await;
                 let ipv4 = Ipv4Packet::new_view(&ipv4_buf).unwrap();
                 debug!("write: {:?}", ipv4);
-                tun.write(ipv4.packet()).await.expect("send");
+                tun.lock().await.write(ipv4.packet()).await.expect("send");
             })
         };
         handles.push(handle);
@@ -230,7 +230,7 @@ fn make_echo_reply_v4(
     buf: &mut [u8],
     icmp_identifier: u16,
     sequence: u16,
-) -> anyhow::Result<EchoReplyPacket> {
+) -> anyhow::Result<EchoReplyPacket<'_>> {
     let mut packet = EchoReplyPacket::new(buf)?;
     packet.set_icmp_type(IcmpType::EchoReply);
     packet.set_icmp_code(IcmpCode(0));
@@ -263,7 +263,7 @@ fn make_tcp_syn_ack<'a>(
     packet.set_destination(tcp_in.get_source());
     packet.set_sequence(0);
     packet.set_acknowledgement(tcp_in.get_sequence() + 1);
-    packet.set_flags(0b00010010);
+    packet.set_flags(0b0001_0010);
     packet.set_window_size(0xFFFF);
     packet.set_checksum(tcp_ipv4_checksum(
         packet.packet(),
diff --git a/crates/trippy-core/tests/sim/tracer.rs b/crates/trippy-core/tests/sim/tracer.rs
index 9f6577d..84f6165 100644
--- a/crates/trippy-core/tests/sim/tracer.rs
+++ b/crates/trippy-core/tests/sim/tracer.rs
@@ -113,7 +113,7 @@ impl Tracer {
 
                     let hop_index = usize::from(complete.ttl.0 - 1);
                     let sim_hop = &self.sim.hops[hop_index];
-                    if let Response::NoResponse = sim_hop.resp {
+                    if matches!(sim_hop.resp, Response::NoResponse) {
                         error_result!(result, anyhow::anyhow!("expected Response::SingleHost"));
                     }
                     let expected_host = match sim_hop.resp {
diff --git a/crates/trippy-core/tests/sim/tun_device.rs b/crates/trippy-core/tests/sim/tun_device.rs
index f2f0068..0b368fd 100644
--- a/crates/trippy-core/tests/sim/tun_device.rs
+++ b/crates/trippy-core/tests/sim/tun_device.rs
@@ -62,11 +62,13 @@ impl TunDevice {
     }
 
     #[cfg(target_os = "linux")]
+    #[allow(clippy::unnecessary_wraps)]
     fn create_route() -> anyhow::Result<()> {
         Ok(())
     }
 
     #[cfg(target_os = "windows")]
+    #[allow(clippy::unnecessary_wraps)]
     fn create_route() -> anyhow::Result<()> {
         // allow time for the routing table to reflect the tun device.
         std::thread::sleep(std::time::Duration::from_millis(10000));
diff --git a/crates/trippy/src/print.rs b/crates/trippy-tui/src/print.rs
similarity index 100%
rename from crates/trippy/src/print.rs
rename to crates/trippy-tui/src/print.rs
diff --git a/crates/trippy/src/report.rs b/crates/trippy-tui/src/report.rs
similarity index 100%
rename from crates/trippy/src/report.rs
rename to crates/trippy-tui/src/report.rs
diff --git a/crates/trippy/src/report/csv.rs b/crates/trippy-tui/src/report/csv.rs
similarity index 100%
rename from crates/trippy/src/report/csv.rs
rename to crates/trippy-tui/src/report/csv.rs
diff --git a/crates/trippy/src/report/dot.rs b/crates/trippy-tui/src/report/dot.rs
similarity index 100%
rename from crates/trippy/src/report/dot.rs
rename to crates/trippy-tui/src/report/dot.rs
diff --git a/crates/trippy/src/report/flows.rs b/crates/trippy-tui/src/report/flows.rs
similarity index 100%
rename from crates/trippy/src/report/flows.rs
rename to crates/trippy-tui/src/report/flows.rs
diff --git a/crates/trippy/src/report/json.rs b/crates/trippy-tui/src/report/json.rs
similarity index 100%
rename from crates/trippy/src/report/json.rs
rename to crates/trippy-tui/src/report/json.rs
diff --git a/crates/trippy/src/report/silent.rs b/crates/trippy-tui/src/report/silent.rs
similarity index 100%
rename from crates/trippy/src/report/silent.rs
rename to crates/trippy-tui/src/report/silent.rs
diff --git a/crates/trippy/src/report/stream.rs b/crates/trippy-tui/src/report/stream.rs
similarity index 100%
rename from crates/trippy/src/report/stream.rs
rename to crates/trippy-tui/src/report/stream.rs
diff --git a/crates/trippy/src/report/table.rs b/crates/trippy-tui/src/report/table.rs
similarity index 100%
rename from crates/trippy/src/report/table.rs
rename to crates/trippy-tui/src/report/table.rs
diff --git a/crates/trippy/src/report/types.rs b/crates/trippy-tui/src/report/types.rs
similarity index 100%
rename from crates/trippy/src/report/types.rs
rename to crates/trippy-tui/src/report/types.rs
diff --git a/crates/trippy/src/util.rs b/crates/trippy-tui/src/util.rs
similarity index 100%
rename from crates/trippy/src/util.rs
rename to crates/trippy-tui/src/util.rs
diff --git a/crates/trippy/tests/resources/snapshots/trip__config__tests__compare_snapshot@trip.snap b/crates/trippy-tui/tests/resources/snapshots/trippy_tui__config__tests__compare_snapshot@trip.snap
similarity index 99%
rename from crates/trippy/tests/resources/snapshots/trip__config__tests__compare_snapshot@trip.snap
rename to crates/trippy-tui/tests/resources/snapshots/trippy_tui__config__tests__compare_snapshot@trip.snap
index 6fd3c06..b0b4557 100644
--- a/crates/trippy/tests/resources/snapshots/trip__config__tests__compare_snapshot@trip.snap
+++ b/crates/trippy-tui/tests/resources/snapshots/trippy_tui__config__tests__compare_snapshot@trip.snap
@@ -1,4 +1,4 @@
 ---
-source: crates/trippy/src/config.rs
+source: crates/trippy-tui/src/config.rs
 ---
 AnetworkdiagnostictoolUsage:trip[OPTIONS][TARGETS]...Arguments:[TARGETS]...AspacedelimitedlistofhostnamesandIPstotraceOptions:-c,--config-file<CONFIG_FILE>Configfile-m,--mode<MODE>Outputmode[default:tui][possiblevalues:tui,stream,pretty,markdown,csv,json,dot,flows,silent]-u,--unprivilegedTracewithoutrequiringelevatedprivilegesonsupportedplatforms[default:false]-p,--protocol<PROTOCOL>Tracingprotocol[default:icmp][possiblevalues:icmp,udp,tcp]--udpTraceusingtheUDPprotocol--tcpTraceusingtheTCPprotocol--icmpTraceusingtheICMPprotocol-F,--addr-family<ADDR_FAMILY>Theaddressfamily[default:Ipv4thenIpv6][possiblevalues:ipv4,ipv6,ipv6-then-ipv4,ipv4-then-ipv6]-4,--ipv4UseIPv4only-6,--ipv6UseIPv6only-P,--target-port<TARGET_PORT>Thetargetport(TCP&UDPonly)[default:80]-S,--source-port<SOURCE_PORT>Thesourceport(TCP&UDPonly)[default:auto]-A,--source-address<SOURCE_ADDRESS>ThesourceIPaddress[default:auto]-I,--interface<INTERFACE>Thenetworkinterface[default:auto]-i,--min-round-duration<MIN_ROUND_DURATION>Theminimumdurationofeveryround[default:1s]-T,--max-round-duration<MAX_ROUND_DURATION>Themaximumdurationofeveryround[default:1s]-g,--grace-duration<GRACE_DURATION>TheperiodoftimetowaitforadditionalICMPresponsesafterthetargethasresponded[default:100ms]--initial-sequence<INITIAL_SEQUENCE>Theinitialsequencenumber[default:33000]-R,--multipath-strategy<MULTIPATH_STRATEGY>TheEqual-costMulti-Pathroutingstrategy(UDPonly)[default:classic][possiblevalues:classic,paris,dublin]-U,--max-inflight<MAX_INFLIGHT>Themaximumnumberofin-flightICMPechorequests[default:24]-f,--first-ttl<FIRST_TTL>TheTTLtostartfrom[default:1]-t,--max-ttl<MAX_TTL>ThemaximumnumberofTTLhops[default:64]--packet-size<PACKET_SIZE>ThesizeofIPpackettosend(IPheader+ICMPheader+payload)[default:84]--payload-pattern<PAYLOAD_PATTERN>TherepeatingpatterninthepayloadoftheICMPpacket[default:0]-Q,--tos<TOS>TheTOS(i.e.DSCP+ECN)IPheadervalue(TCPandUDPonly)[default:0]-e,--icmp-extensionsParseICMPextensions--read-timeout<READ_TIMEOUT>Thesocketreadtimeout[default:10ms]-r,--dns-resolve-method<DNS_RESOLVE_METHOD>HowtoperformDNSqueries[default:system][possiblevalues:system,resolv,google,cloudflare]-y,--dns-resolve-allTracetoallIPsresolvedfromDNSlookup[default:false]--dns-timeout<DNS_TIMEOUT>ThemaximumtimetowaittoperformDNSqueries[default:5s]-z,--dns-lookup-as-infoLookupautonomoussystem(AS)informationduringDNSqueries[default:false]-s,--max-samples<MAX_SAMPLES>Themaximumnumberofsamplestorecordperhop[default:256]--max-flows<MAX_FLOWS>Themaximumnumberofflowstorecord[default:64]-a,--tui-address-mode<TUI_ADDRESS_MODE>Howtorenderaddresses[default:host][possiblevalues:ip,host,both]--tui-as-mode<TUI_AS_MODE>HowtorenderASinformation[default:asn][possiblevalues:asn,prefix,country-code,registry,allocated,name]--tui-custom-columns<TUI_CUSTOM_COLUMNS>CustomcolumnstobedisplayedintheTUIhopstable[default:holsravbwdt]--tui-icmp-extension-mode<TUI_ICMP_EXTENSION_MODE>HowtorenderICMPextensions[default:off][possiblevalues:off,mpls,full,all]--tui-geoip-mode<TUI_GEOIP_MODE>HowtorenderGeoIpinformation[default:short][possiblevalues:off,short,long,location]-M,--tui-max-addrs<TUI_MAX_ADDRS>Themaximumnumberofaddressestoshowperhop[default:auto]--tui-preserve-screenPreservethescreenonexit[default:false]--tui-refresh-rate<TUI_REFRESH_RATE>TheTuirefreshrate[default:100ms]--tui-privacy-max-ttl<TUI_PRIVACY_MAX_TTL>Themaximumttlofhopswhichwillbemaskedforprivacy[default:0]--tui-theme-colors<TUI_THEME_COLORS>TheTUIthemecolors[item=color,item=color,..]--print-tui-theme-itemsPrintallTUIthemeitemsandexit--tui-key-bindings<TUI_KEY_BINDINGS>TheTUIkeybindings[command=key,command=key,..]--print-tui-binding-commandsPrintallTUIcommandsthatcanbeboundandexit-C,--report-cycles<REPORT_CYCLES>Thenumberofreportcyclestorun[default:10]-G,--geoip-mmdb-file<GEOIP_MMDB_FILE>ThesupportedMaxMindorIPinfoGeoIpmmdbfile--generate<GENERATE>Generateshellcompletion[possiblevalues:bash,elvish,fish,powershell,zsh]--generate-manGenerateROFFmanpage--print-config-templatePrintatemplatetomlconfigfileandexit--log-format<LOG_FORMAT>Thedebuglogformat[default:pretty][possiblevalues:compact,pretty,json,chrome]--log-filter<LOG_FILTER>Thedebuglogfilter[default:trippy=debug]--log-span-events<LOG_SPAN_EVENTS>Thedebuglogformat[default:off][possiblevalues:off,active,full]-v,--verboseEnableverbosedebuglogging-h,--helpPrinthelp(seemorewith'--help')-V,--versionPrintversion
diff --git a/crates/trippy/tests/resources/snapshots/trip__config__tests__compare_snapshot@trip_--help.snap b/crates/trippy-tui/tests/resources/snapshots/trippy_tui__config__tests__compare_snapshot@trip_--help.snap
similarity index 99%
rename from crates/trippy/tests/resources/snapshots/trip__config__tests__compare_snapshot@trip_--help.snap
rename to crates/trippy-tui/tests/resources/snapshots/trippy_tui__config__tests__compare_snapshot@trip_--help.snap
index be40713..29220ba 100644
--- a/crates/trippy/tests/resources/snapshots/trip__config__tests__compare_snapshot@trip_--help.snap
+++ b/crates/trippy-tui/tests/resources/snapshots/trippy_tui__config__tests__compare_snapshot@trip_--help.snap
@@ -1,4 +1,4 @@
 ---
-source: crates/trippy/src/config.rs
+source: crates/trippy-tui/src/config.rs
 ---
 AnetworkdiagnostictoolUsage:trip[OPTIONS][TARGETS]...Arguments:[TARGETS]...AspacedelimitedlistofhostnamesandIPstotraceOptions:-c,--config-file<CONFIG_FILE>Configfile-m,--mode<MODE>Outputmode[default:tui]Possiblevalues:-tui:DisplayinteractiveTUI-stream:Displayacontinuousstreamoftracingdata-pretty:GenerateaprettytexttablereportforNcycles-markdown:GenerateaMarkdowntexttablereportforNcycles-csv:GenerateaCSVreportforNcycles-json:GenerateaJSONreportforNcycles-dot:GenerateaGraphvizDOTfileforNcycles-flows:DisplayallflowsforNcycles-silent:DonotgenerateanytracingoutputforNcycles-u,--unprivilegedTracewithoutrequiringelevatedprivilegesonsupportedplatforms[default:false]-p,--protocol<PROTOCOL>Tracingprotocol[default:icmp]Possiblevalues:-icmp:InternetControlMessageProtocol-udp:UserDatagramProtocol-tcp:TransmissionControlProtocol--udpTraceusingtheUDPprotocol--tcpTraceusingtheTCPprotocol--icmpTraceusingtheICMPprotocol-F,--addr-family<ADDR_FAMILY>Theaddressfamily[default:Ipv4thenIpv6]Possiblevalues:-ipv4:Ipv4only-ipv6:Ipv6only-ipv6-then-ipv4:Ipv6withafallbacktoIpv4-ipv4-then-ipv6:Ipv4withafallbacktoIpv6-4,--ipv4UseIPv4only-6,--ipv6UseIPv6only-P,--target-port<TARGET_PORT>Thetargetport(TCP&UDPonly)[default:80]-S,--source-port<SOURCE_PORT>Thesourceport(TCP&UDPonly)[default:auto]-A,--source-address<SOURCE_ADDRESS>ThesourceIPaddress[default:auto]-I,--interface<INTERFACE>Thenetworkinterface[default:auto]-i,--min-round-duration<MIN_ROUND_DURATION>Theminimumdurationofeveryround[default:1s]-T,--max-round-duration<MAX_ROUND_DURATION>Themaximumdurationofeveryround[default:1s]-g,--grace-duration<GRACE_DURATION>TheperiodoftimetowaitforadditionalICMPresponsesafterthetargethasresponded[default:100ms]--initial-sequence<INITIAL_SEQUENCE>Theinitialsequencenumber[default:33000]-R,--multipath-strategy<MULTIPATH_STRATEGY>TheEqual-costMulti-Pathroutingstrategy(UDPonly)[default:classic]Possiblevalues:-classic:Thesrcordestportisusedtostorethesequencenumber-paris:TheUDP`checksum`fieldisusedtostorethesequencenumber-dublin:TheIP`identifier`fieldisusedtostorethesequencenumber-U,--max-inflight<MAX_INFLIGHT>Themaximumnumberofin-flightICMPechorequests[default:24]-f,--first-ttl<FIRST_TTL>TheTTLtostartfrom[default:1]-t,--max-ttl<MAX_TTL>ThemaximumnumberofTTLhops[default:64]--packet-size<PACKET_SIZE>ThesizeofIPpackettosend(IPheader+ICMPheader+payload)[default:84]--payload-pattern<PAYLOAD_PATTERN>TherepeatingpatterninthepayloadoftheICMPpacket[default:0]-Q,--tos<TOS>TheTOS(i.e.DSCP+ECN)IPheadervalue(TCPandUDPonly)[default:0]-e,--icmp-extensionsParseICMPextensions--read-timeout<READ_TIMEOUT>Thesocketreadtimeout[default:10ms]-r,--dns-resolve-method<DNS_RESOLVE_METHOD>HowtoperformDNSqueries[default:system]Possiblevalues:-system:ResolveusingtheOSresolver-resolv:Resolveusingthe`/etc/resolv.conf`DNSconfiguration-google:ResolveusingtheGoogle`8.8.8.8`DNSservice-cloudflare:ResolveusingtheCloudflare`1.1.1.1`DNSservice-y,--dns-resolve-allTracetoallIPsresolvedfromDNSlookup[default:false]--dns-timeout<DNS_TIMEOUT>ThemaximumtimetowaittoperformDNSqueries[default:5s]-z,--dns-lookup-as-infoLookupautonomoussystem(AS)informationduringDNSqueries[default:false]-s,--max-samples<MAX_SAMPLES>Themaximumnumberofsamplestorecordperhop[default:256]--max-flows<MAX_FLOWS>Themaximumnumberofflowstorecord[default:64]-a,--tui-address-mode<TUI_ADDRESS_MODE>Howtorenderaddresses[default:host]Possiblevalues:-ip:ShowIPaddressonly-host:Showreverse-lookupDNShostnameonly-both:ShowbothIPaddressandreverse-lookupDNShostname--tui-as-mode<TUI_AS_MODE>HowtorenderASinformation[default:asn]Possiblevalues:-asn:ShowtheASN-prefix:DisplaytheASprefix-country-code:Displaythecountrycode-registry:Displaytheregistryname-allocated:Displaytheallocateddate-name:DisplaytheASname--tui-custom-columns<TUI_CUSTOM_COLUMNS>CustomcolumnstobedisplayedintheTUIhopstable[default:holsravbwdt]--tui-icmp-extension-mode<TUI_ICMP_EXTENSION_MODE>HowtorenderICMPextensions[default:off]Possiblevalues:-off:Donotshow`icmp`extensions-mpls:ShowMPLSlabel(s)only-full:Showfull`icmp`extensiondataforallknownextensions-all:Showfull`icmp`extensiondataforallclasses--tui-geoip-mode<TUI_GEOIP_MODE>HowtorenderGeoIpinformation[default:short]Possiblevalues:-off:DonotdisplayGeoIpdata-short:Showshortformat-long:Showlongformat-location:ShowlatitudeandLongitudeformat-M,--tui-max-addrs<TUI_MAX_ADDRS>Themaximumnumberofaddressestoshowperhop[default:auto]--tui-preserve-screenPreservethescreenonexit[default:false]--tui-refresh-rate<TUI_REFRESH_RATE>TheTuirefreshrate[default:100ms]--tui-privacy-max-ttl<TUI_PRIVACY_MAX_TTL>Themaximumttlofhopswhichwillbemaskedforprivacy[default:0]--tui-theme-colors<TUI_THEME_COLORS>TheTUIthemecolors[item=color,item=color,..]--print-tui-theme-itemsPrintallTUIthemeitemsandexit--tui-key-bindings<TUI_KEY_BINDINGS>TheTUIkeybindings[command=key,command=key,..]--print-tui-binding-commandsPrintallTUIcommandsthatcanbeboundandexit-C,--report-cycles<REPORT_CYCLES>Thenumberofreportcyclestorun[default:10]-G,--geoip-mmdb-file<GEOIP_MMDB_FILE>ThesupportedMaxMindorIPinfoGeoIpmmdbfile--generate<GENERATE>Generateshellcompletion[possiblevalues:bash,elvish,fish,powershell,zsh]--generate-manGenerateROFFmanpage--print-config-templatePrintatemplatetomlconfigfileandexit--log-format<LOG_FORMAT>Thedebuglogformat[default:pretty]Possiblevalues:-compact:Displaylogdatainacompactformat-pretty:Displaylogdatainaprettyformat-json:Displaylogdatainajsonformat-chrome:DisplaylogdatainChrometraceformat--log-filter<LOG_FILTER>Thedebuglogfilter[default:trippy=debug]--log-span-events<LOG_SPAN_EVENTS>Thedebuglogformat[default:off]Possiblevalues:-off:Donotdisplayeventspans-active:Displayenterandexiteventspans-full:Displayalleventspans-v,--verboseEnableverbosedebuglogging-h,--helpPrinthelp(seeasummarywith'-h')-V,--versionPrintversion
diff --git a/crates/trippy/tests/resources/snapshots/trip__config__tests__compare_snapshot@trip_-h.snap b/crates/trippy-tui/tests/resources/snapshots/trippy_tui__config__tests__compare_snapshot@trip_-h.snap
similarity index 99%
rename from crates/trippy/tests/resources/snapshots/trip__config__tests__compare_snapshot@trip_-h.snap
rename to crates/trippy-tui/tests/resources/snapshots/trippy_tui__config__tests__compare_snapshot@trip_-h.snap
index 6fd3c06..b0b4557 100644
--- a/crates/trippy/tests/resources/snapshots/trip__config__tests__compare_snapshot@trip_-h.snap
+++ b/crates/trippy-tui/tests/resources/snapshots/trippy_tui__config__tests__compare_snapshot@trip_-h.snap
@@ -1,4 +1,4 @@
 ---
-source: crates/trippy/src/config.rs
+source: crates/trippy-tui/src/config.rs
 ---
 AnetworkdiagnostictoolUsage:trip[OPTIONS][TARGETS]...Arguments:[TARGETS]...AspacedelimitedlistofhostnamesandIPstotraceOptions:-c,--config-file<CONFIG_FILE>Configfile-m,--mode<MODE>Outputmode[default:tui][possiblevalues:tui,stream,pretty,markdown,csv,json,dot,flows,silent]-u,--unprivilegedTracewithoutrequiringelevatedprivilegesonsupportedplatforms[default:false]-p,--protocol<PROTOCOL>Tracingprotocol[default:icmp][possiblevalues:icmp,udp,tcp]--udpTraceusingtheUDPprotocol--tcpTraceusingtheTCPprotocol--icmpTraceusingtheICMPprotocol-F,--addr-family<ADDR_FAMILY>Theaddressfamily[default:Ipv4thenIpv6][possiblevalues:ipv4,ipv6,ipv6-then-ipv4,ipv4-then-ipv6]-4,--ipv4UseIPv4only-6,--ipv6UseIPv6only-P,--target-port<TARGET_PORT>Thetargetport(TCP&UDPonly)[default:80]-S,--source-port<SOURCE_PORT>Thesourceport(TCP&UDPonly)[default:auto]-A,--source-address<SOURCE_ADDRESS>ThesourceIPaddress[default:auto]-I,--interface<INTERFACE>Thenetworkinterface[default:auto]-i,--min-round-duration<MIN_ROUND_DURATION>Theminimumdurationofeveryround[default:1s]-T,--max-round-duration<MAX_ROUND_DURATION>Themaximumdurationofeveryround[default:1s]-g,--grace-duration<GRACE_DURATION>TheperiodoftimetowaitforadditionalICMPresponsesafterthetargethasresponded[default:100ms]--initial-sequence<INITIAL_SEQUENCE>Theinitialsequencenumber[default:33000]-R,--multipath-strategy<MULTIPATH_STRATEGY>TheEqual-costMulti-Pathroutingstrategy(UDPonly)[default:classic][possiblevalues:classic,paris,dublin]-U,--max-inflight<MAX_INFLIGHT>Themaximumnumberofin-flightICMPechorequests[default:24]-f,--first-ttl<FIRST_TTL>TheTTLtostartfrom[default:1]-t,--max-ttl<MAX_TTL>ThemaximumnumberofTTLhops[default:64]--packet-size<PACKET_SIZE>ThesizeofIPpackettosend(IPheader+ICMPheader+payload)[default:84]--payload-pattern<PAYLOAD_PATTERN>TherepeatingpatterninthepayloadoftheICMPpacket[default:0]-Q,--tos<TOS>TheTOS(i.e.DSCP+ECN)IPheadervalue(TCPandUDPonly)[default:0]-e,--icmp-extensionsParseICMPextensions--read-timeout<READ_TIMEOUT>Thesocketreadtimeout[default:10ms]-r,--dns-resolve-method<DNS_RESOLVE_METHOD>HowtoperformDNSqueries[default:system][possiblevalues:system,resolv,google,cloudflare]-y,--dns-resolve-allTracetoallIPsresolvedfromDNSlookup[default:false]--dns-timeout<DNS_TIMEOUT>ThemaximumtimetowaittoperformDNSqueries[default:5s]-z,--dns-lookup-as-infoLookupautonomoussystem(AS)informationduringDNSqueries[default:false]-s,--max-samples<MAX_SAMPLES>Themaximumnumberofsamplestorecordperhop[default:256]--max-flows<MAX_FLOWS>Themaximumnumberofflowstorecord[default:64]-a,--tui-address-mode<TUI_ADDRESS_MODE>Howtorenderaddresses[default:host][possiblevalues:ip,host,both]--tui-as-mode<TUI_AS_MODE>HowtorenderASinformation[default:asn][possiblevalues:asn,prefix,country-code,registry,allocated,name]--tui-custom-columns<TUI_CUSTOM_COLUMNS>CustomcolumnstobedisplayedintheTUIhopstable[default:holsravbwdt]--tui-icmp-extension-mode<TUI_ICMP_EXTENSION_MODE>HowtorenderICMPextensions[default:off][possiblevalues:off,mpls,full,all]--tui-geoip-mode<TUI_GEOIP_MODE>HowtorenderGeoIpinformation[default:short][possiblevalues:off,short,long,location]-M,--tui-max-addrs<TUI_MAX_ADDRS>Themaximumnumberofaddressestoshowperhop[default:auto]--tui-preserve-screenPreservethescreenonexit[default:false]--tui-refresh-rate<TUI_REFRESH_RATE>TheTuirefreshrate[default:100ms]--tui-privacy-max-ttl<TUI_PRIVACY_MAX_TTL>Themaximumttlofhopswhichwillbemaskedforprivacy[default:0]--tui-theme-colors<TUI_THEME_COLORS>TheTUIthemecolors[item=color,item=color,..]--print-tui-theme-itemsPrintallTUIthemeitemsandexit--tui-key-bindings<TUI_KEY_BINDINGS>TheTUIkeybindings[command=key,command=key,..]--print-tui-binding-commandsPrintallTUIcommandsthatcanbeboundandexit-C,--report-cycles<REPORT_CYCLES>Thenumberofreportcyclestorun[default:10]-G,--geoip-mmdb-file<GEOIP_MMDB_FILE>ThesupportedMaxMindorIPinfoGeoIpmmdbfile--generate<GENERATE>Generateshellcompletion[possiblevalues:bash,elvish,fish,powershell,zsh]--generate-manGenerateROFFmanpage--print-config-templatePrintatemplatetomlconfigfileandexit--log-format<LOG_FORMAT>Thedebuglogformat[default:pretty][possiblevalues:compact,pretty,json,chrome]--log-filter<LOG_FILTER>Thedebuglogfilter[default:trippy=debug]--log-span-events<LOG_SPAN_EVENTS>Thedebuglogformat[default:off][possiblevalues:off,active,full]-v,--verboseEnableverbosedebuglogging-h,--helpPrinthelp(seemorewith'--help')-V,--versionPrintversion
diff --git a/crates/trippy/tests/resources/snapshots/trip__print__tests__output@generate_bash_shell_completions.snap b/crates/trippy-tui/tests/resources/snapshots/trippy_tui__print__tests__output@generate_bash_shell_completions.snap
similarity index 99%
rename from crates/trippy/tests/resources/snapshots/trip__print__tests__output@generate_bash_shell_completions.snap
rename to crates/trippy-tui/tests/resources/snapshots/trippy_tui__print__tests__output@generate_bash_shell_completions.snap
index b78dd64..a40b4b4 100644
--- a/crates/trippy/tests/resources/snapshots/trip__print__tests__output@generate_bash_shell_completions.snap
+++ b/crates/trippy-tui/tests/resources/snapshots/trippy_tui__print__tests__output@generate_bash_shell_completions.snap
@@ -1,4 +1,4 @@
 ---
-source: crates/trippy/src/print.rs
+source: crates/trippy-tui/src/print.rs
 ---
 _trip(){localicurprevoptscmdCOMPREPLY=()cur="${COMP_WORDS[COMP_CWORD]}"prev="${COMP_WORDS[COMP_CWORD-1]}"cmd=""opts=""foriin${COMP_WORDS[@]}docase"${cmd},${i}"in",$1")cmd="trip";;*);;esacdonecase"${cmd}"intrip)opts="-c-m-u-p-F-4-6-P-S-A-I-i-T-g-R-U-f-t-Q-e-r-y-z-s-a-M-C-G-v-h-V--config-file--mode--unprivileged--protocol--udp--tcp--icmp--addr-family--ipv4--ipv6--target-port--source-port--source-address--interface--min-round-duration--max-round-duration--grace-duration--initial-sequence--multipath-strategy--max-inflight--first-ttl--max-ttl--packet-size--payload-pattern--tos--icmp-extensions--read-timeout--dns-resolve-method--dns-resolve-all--dns-timeout--dns-lookup-as-info--max-samples--max-flows--tui-address-mode--tui-as-mode--tui-custom-columns--tui-icmp-extension-mode--tui-geoip-mode--tui-max-addrs--tui-preserve-screen--tui-refresh-rate--tui-privacy-max-ttl--tui-theme-colors--print-tui-theme-items--tui-key-bindings--print-tui-binding-commands--report-cycles--geoip-mmdb-file--generate--generate-man--print-config-template--log-format--log-filter--log-span-events--verbose--help--version[TARGETS]..."if[[${cur}==-*||${COMP_CWORD}-eq1]];thenCOMPREPLY=($(compgen-W"${opts}"--"${cur}"))return0ficase"${prev}"in--config-file)localoldifsif[-n"${IFS+x}"];thenoldifs="$IFS"fiIFS=$'\n'COMPREPLY=($(compgen-f"${cur}"))if[-n"${oldifs+x}"];thenIFS="$oldifs"fiif[["${BASH_VERSINFO[0]}"-ge4]];thencompopt-ofilenamesfireturn0;;-c)localoldifsif[-n"${IFS+x}"];thenoldifs="$IFS"fiIFS=$'\n'COMPREPLY=($(compgen-f"${cur}"))if[-n"${oldifs+x}"];thenIFS="$oldifs"fiif[["${BASH_VERSINFO[0]}"-ge4]];thencompopt-ofilenamesfireturn0;;--mode)COMPREPLY=($(compgen-W"tuistreamprettymarkdowncsvjsondotflowssilent"--"${cur}"))return0;;-m)COMPREPLY=($(compgen-W"tuistreamprettymarkdowncsvjsondotflowssilent"--"${cur}"))return0;;--protocol)COMPREPLY=($(compgen-W"icmpudptcp"--"${cur}"))return0;;-p)COMPREPLY=($(compgen-W"icmpudptcp"--"${cur}"))return0;;--addr-family)COMPREPLY=($(compgen-W"ipv4ipv6ipv6-then-ipv4ipv4-then-ipv6"--"${cur}"))return0;;-F)COMPREPLY=($(compgen-W"ipv4ipv6ipv6-then-ipv4ipv4-then-ipv6"--"${cur}"))return0;;--target-port)COMPREPLY=($(compgen-f"${cur}"))return0;;-P)COMPREPLY=($(compgen-f"${cur}"))return0;;--source-port)COMPREPLY=($(compgen-f"${cur}"))return0;;-S)COMPREPLY=($(compgen-f"${cur}"))return0;;--source-address)COMPREPLY=($(compgen-f"${cur}"))return0;;-A)COMPREPLY=($(compgen-f"${cur}"))return0;;--interface)COMPREPLY=($(compgen-f"${cur}"))return0;;-I)COMPREPLY=($(compgen-f"${cur}"))return0;;--min-round-duration)COMPREPLY=($(compgen-f"${cur}"))return0;;-i)COMPREPLY=($(compgen-f"${cur}"))return0;;--max-round-duration)COMPREPLY=($(compgen-f"${cur}"))return0;;-T)COMPREPLY=($(compgen-f"${cur}"))return0;;--grace-duration)COMPREPLY=($(compgen-f"${cur}"))return0;;-g)COMPREPLY=($(compgen-f"${cur}"))return0;;--initial-sequence)COMPREPLY=($(compgen-f"${cur}"))return0;;--multipath-strategy)COMPREPLY=($(compgen-W"classicparisdublin"--"${cur}"))return0;;-R)COMPREPLY=($(compgen-W"classicparisdublin"--"${cur}"))return0;;--max-inflight)COMPREPLY=($(compgen-f"${cur}"))return0;;-U)COMPREPLY=($(compgen-f"${cur}"))return0;;--first-ttl)COMPREPLY=($(compgen-f"${cur}"))return0;;-f)COMPREPLY=($(compgen-f"${cur}"))return0;;--max-ttl)COMPREPLY=($(compgen-f"${cur}"))return0;;-t)COMPREPLY=($(compgen-f"${cur}"))return0;;--packet-size)COMPREPLY=($(compgen-f"${cur}"))return0;;--payload-pattern)COMPREPLY=($(compgen-f"${cur}"))return0;;--tos)COMPREPLY=($(compgen-f"${cur}"))return0;;-Q)COMPREPLY=($(compgen-f"${cur}"))return0;;--read-timeout)COMPREPLY=($(compgen-f"${cur}"))return0;;--dns-resolve-method)COMPREPLY=($(compgen-W"systemresolvgooglecloudflare"--"${cur}"))return0;;-r)COMPREPLY=($(compgen-W"systemresolvgooglecloudflare"--"${cur}"))return0;;--dns-timeout)COMPREPLY=($(compgen-f"${cur}"))return0;;--max-samples)COMPREPLY=($(compgen-f"${cur}"))return0;;-s)COMPREPLY=($(compgen-f"${cur}"))return0;;--max-flows)COMPREPLY=($(compgen-f"${cur}"))return0;;--tui-address-mode)COMPREPLY=($(compgen-W"iphostboth"--"${cur}"))return0;;-a)COMPREPLY=($(compgen-W"iphostboth"--"${cur}"))return0;;--tui-as-mode)COMPREPLY=($(compgen-W"asnprefixcountry-coderegistryallocatedname"--"${cur}"))return0;;--tui-custom-columns)COMPREPLY=($(compgen-f"${cur}"))return0;;--tui-icmp-extension-mode)COMPREPLY=($(compgen-W"offmplsfullall"--"${cur}"))return0;;--tui-geoip-mode)COMPREPLY=($(compgen-W"offshortlonglocation"--"${cur}"))return0;;--tui-max-addrs)COMPREPLY=($(compgen-f"${cur}"))return0;;-M)COMPREPLY=($(compgen-f"${cur}"))return0;;--tui-refresh-rate)COMPREPLY=($(compgen-f"${cur}"))return0;;--tui-privacy-max-ttl)COMPREPLY=($(compgen-f"${cur}"))return0;;--tui-theme-colors)COMPREPLY=($(compgen-f"${cur}"))return0;;--tui-key-bindings)COMPREPLY=($(compgen-f"${cur}"))return0;;--report-cycles)COMPREPLY=($(compgen-f"${cur}"))return0;;-C)COMPREPLY=($(compgen-f"${cur}"))return0;;--geoip-mmdb-file)localoldifsif[-n"${IFS+x}"];thenoldifs="$IFS"fiIFS=$'\n'COMPREPLY=($(compgen-f"${cur}"))if[-n"${oldifs+x}"];thenIFS="$oldifs"fiif[["${BASH_VERSINFO[0]}"-ge4]];thencompopt-ofilenamesfireturn0;;-G)localoldifsif[-n"${IFS+x}"];thenoldifs="$IFS"fiIFS=$'\n'COMPREPLY=($(compgen-f"${cur}"))if[-n"${oldifs+x}"];thenIFS="$oldifs"fiif[["${BASH_VERSINFO[0]}"-ge4]];thencompopt-ofilenamesfireturn0;;--generate)COMPREPLY=($(compgen-W"bashelvishfishpowershellzsh"--"${cur}"))return0;;--log-format)COMPREPLY=($(compgen-W"compactprettyjsonchrome"--"${cur}"))return0;;--log-filter)COMPREPLY=($(compgen-f"${cur}"))return0;;--log-span-events)COMPREPLY=($(compgen-W"offactivefull"--"${cur}"))return0;;*)COMPREPLY=();;esacCOMPREPLY=($(compgen-W"${opts}"--"${cur}"))return0;;esac}if[["${BASH_VERSINFO[0]}"-eq4&&"${BASH_VERSINFO[1]}"-ge4||"${BASH_VERSINFO[0]}"-gt4]];thencomplete-F_trip-onosort-obashdefault-odefaulttripelsecomplete-F_trip-obashdefault-odefaulttripfi
diff --git a/crates/trippy/tests/resources/snapshots/trip__print__tests__output@generate_elvish_shell_completions.snap b/crates/trippy-tui/tests/resources/snapshots/trippy_tui__print__tests__output@generate_elvish_shell_completions.snap
similarity index 99%
rename from crates/trippy/tests/resources/snapshots/trip__print__tests__output@generate_elvish_shell_completions.snap
rename to crates/trippy-tui/tests/resources/snapshots/trippy_tui__print__tests__output@generate_elvish_shell_completions.snap
index 05ae47f..4034f87 100644
--- a/crates/trippy/tests/resources/snapshots/trip__print__tests__output@generate_elvish_shell_completions.snap
+++ b/crates/trippy-tui/tests/resources/snapshots/trippy_tui__print__tests__output@generate_elvish_shell_completions.snap
@@ -1,4 +1,4 @@
 ---
-source: crates/trippy/src/print.rs
+source: crates/trippy-tui/src/print.rs
 ---
 usebuiltin;usestr;setedit:completion:arg-completer[trip]={|@words|fnspaces{|n|builtin:repeat$n''|str:join''}fncand{|textdesc|edit:complex-candidate$text&display=$text''(spaces(-14(wcswidth$text)))$desc}varcommand='trip'forword$words[1..-1]{if(str:has-prefix$word'-'){break}setcommand=$command';'$word}varcompletions=[&'trip'={cand-c'Configfile'cand--config-file'Configfile'cand-m'Outputmode[default:tui]'cand--mode'Outputmode[default:tui]'cand-p'Tracingprotocol[default:icmp]'cand--protocol'Tracingprotocol[default:icmp]'cand-F'Theaddressfamily[default:Ipv4thenIpv6]'cand--addr-family'Theaddressfamily[default:Ipv4thenIpv6]'cand-P'Thetargetport(TCP&UDPonly)[default:80]'cand--target-port'Thetargetport(TCP&UDPonly)[default:80]'cand-S'Thesourceport(TCP&UDPonly)[default:auto]'cand--source-port'Thesourceport(TCP&UDPonly)[default:auto]'cand-A'ThesourceIPaddress[default:auto]'cand--source-address'ThesourceIPaddress[default:auto]'cand-I'Thenetworkinterface[default:auto]'cand--interface'Thenetworkinterface[default:auto]'cand-i'Theminimumdurationofeveryround[default:1s]'cand--min-round-duration'Theminimumdurationofeveryround[default:1s]'cand-T'Themaximumdurationofeveryround[default:1s]'cand--max-round-duration'Themaximumdurationofeveryround[default:1s]'cand-g'TheperiodoftimetowaitforadditionalICMPresponsesafterthetargethasresponded[default:100ms]'cand--grace-duration'TheperiodoftimetowaitforadditionalICMPresponsesafterthetargethasresponded[default:100ms]'cand--initial-sequence'Theinitialsequencenumber[default:33000]'cand-R'TheEqual-costMulti-Pathroutingstrategy(UDPonly)[default:classic]'cand--multipath-strategy'TheEqual-costMulti-Pathroutingstrategy(UDPonly)[default:classic]'cand-U'Themaximumnumberofin-flightICMPechorequests[default:24]'cand--max-inflight'Themaximumnumberofin-flightICMPechorequests[default:24]'cand-f'TheTTLtostartfrom[default:1]'cand--first-ttl'TheTTLtostartfrom[default:1]'cand-t'ThemaximumnumberofTTLhops[default:64]'cand--max-ttl'ThemaximumnumberofTTLhops[default:64]'cand--packet-size'ThesizeofIPpackettosend(IPheader+ICMPheader+payload)[default:84]'cand--payload-pattern'TherepeatingpatterninthepayloadoftheICMPpacket[default:0]'cand-Q'TheTOS(i.e.DSCP+ECN)IPheadervalue(TCPandUDPonly)[default:0]'cand--tos'TheTOS(i.e.DSCP+ECN)IPheadervalue(TCPandUDPonly)[default:0]'cand--read-timeout'Thesocketreadtimeout[default:10ms]'cand-r'HowtoperformDNSqueries[default:system]'cand--dns-resolve-method'HowtoperformDNSqueries[default:system]'cand--dns-timeout'ThemaximumtimetowaittoperformDNSqueries[default:5s]'cand-s'Themaximumnumberofsamplestorecordperhop[default:256]'cand--max-samples'Themaximumnumberofsamplestorecordperhop[default:256]'cand--max-flows'Themaximumnumberofflowstorecord[default:64]'cand-a'Howtorenderaddresses[default:host]'cand--tui-address-mode'Howtorenderaddresses[default:host]'cand--tui-as-mode'HowtorenderASinformation[default:asn]'cand--tui-custom-columns'CustomcolumnstobedisplayedintheTUIhopstable[default:holsravbwdt]'cand--tui-icmp-extension-mode'HowtorenderICMPextensions[default:off]'cand--tui-geoip-mode'HowtorenderGeoIpinformation[default:short]'cand-M'Themaximumnumberofaddressestoshowperhop[default:auto]'cand--tui-max-addrs'Themaximumnumberofaddressestoshowperhop[default:auto]'cand--tui-refresh-rate'TheTuirefreshrate[default:100ms]'cand--tui-privacy-max-ttl'Themaximumttlofhopswhichwillbemaskedforprivacy[default:0]'cand--tui-theme-colors'TheTUIthemecolors[item=color,item=color,..]'cand--tui-key-bindings'TheTUIkeybindings[command=key,command=key,..]'cand-C'Thenumberofreportcyclestorun[default:10]'cand--report-cycles'Thenumberofreportcyclestorun[default:10]'cand-G'ThesupportedMaxMindorIPinfoGeoIpmmdbfile'cand--geoip-mmdb-file'ThesupportedMaxMindorIPinfoGeoIpmmdbfile'cand--generate'Generateshellcompletion'cand--log-format'Thedebuglogformat[default:pretty]'cand--log-filter'Thedebuglogfilter[default:trippy=debug]'cand--log-span-events'Thedebuglogformat[default:off]'cand-u'Tracewithoutrequiringelevatedprivilegesonsupportedplatforms[default:false]'cand--unprivileged'Tracewithoutrequiringelevatedprivilegesonsupportedplatforms[default:false]'cand--udp'TraceusingtheUDPprotocol'cand--tcp'TraceusingtheTCPprotocol'cand--icmp'TraceusingtheICMPprotocol'cand-4'UseIPv4only'cand--ipv4'UseIPv4only'cand-6'UseIPv6only'cand--ipv6'UseIPv6only'cand-e'ParseICMPextensions'cand--icmp-extensions'ParseICMPextensions'cand-y'TracetoallIPsresolvedfromDNSlookup[default:false]'cand--dns-resolve-all'TracetoallIPsresolvedfromDNSlookup[default:false]'cand-z'Lookupautonomoussystem(AS)informationduringDNSqueries[default:false]'cand--dns-lookup-as-info'Lookupautonomoussystem(AS)informationduringDNSqueries[default:false]'cand--tui-preserve-screen'Preservethescreenonexit[default:false]'cand--print-tui-theme-items'PrintallTUIthemeitemsandexit'cand--print-tui-binding-commands'PrintallTUIcommandsthatcanbeboundandexit'cand--generate-man'GenerateROFFmanpage'cand--print-config-template'Printatemplatetomlconfigfileandexit'cand-v'Enableverbosedebuglogging'cand--verbose'Enableverbosedebuglogging'cand-h'Printhelp(seemorewith''--help'')'cand--help'Printhelp(seemorewith''--help'')'cand-V'Printversion'cand--version'Printversion'}]$completions[$command]}
diff --git a/crates/trippy/tests/resources/snapshots/trip__print__tests__output@generate_fish_shell_completions.snap b/crates/trippy-tui/tests/resources/snapshots/trippy_tui__print__tests__output@generate_fish_shell_completions.snap
similarity index 99%
rename from crates/trippy/tests/resources/snapshots/trip__print__tests__output@generate_fish_shell_completions.snap
rename to crates/trippy-tui/tests/resources/snapshots/trippy_tui__print__tests__output@generate_fish_shell_completions.snap
index 35ea7f6..59ea85c 100644
--- a/crates/trippy/tests/resources/snapshots/trip__print__tests__output@generate_fish_shell_completions.snap
+++ b/crates/trippy-tui/tests/resources/snapshots/trippy_tui__print__tests__output@generate_fish_shell_completions.snap
@@ -1,4 +1,4 @@
 ---
-source: crates/trippy/src/print.rs
+source: crates/trippy-tui/src/print.rs
 ---
 complete-ctrip-sc-lconfig-file-d'Configfile'-r-Fcomplete-ctrip-sm-lmode-d'Outputmode[default:tui]'-r-f-a"{tui'DisplayinteractiveTUI',stream'Displayacontinuousstreamoftracingdata',pretty'GenerateaprettytexttablereportforNcycles',markdown'GenerateaMarkdowntexttablereportforNcycles',csv'GenerateaCSVreportforNcycles',json'GenerateaJSONreportforNcycles',dot'GenerateaGraphvizDOTfileforNcycles',flows'DisplayallflowsforNcycles',silent'DonotgenerateanytracingoutputforNcycles'}"complete-ctrip-sp-lprotocol-d'Tracingprotocol[default:icmp]'-r-f-a"{icmp'InternetControlMessageProtocol',udp'UserDatagramProtocol',tcp'TransmissionControlProtocol'}"complete-ctrip-sF-laddr-family-d'Theaddressfamily[default:Ipv4thenIpv6]'-r-f-a"{ipv4'Ipv4only',ipv6'Ipv6only',ipv6-then-ipv4'Ipv6withafallbacktoIpv4',ipv4-then-ipv6'Ipv4withafallbacktoIpv6'}"complete-ctrip-sP-ltarget-port-d'Thetargetport(TCP&UDPonly)[default:80]'-rcomplete-ctrip-sS-lsource-port-d'Thesourceport(TCP&UDPonly)[default:auto]'-rcomplete-ctrip-sA-lsource-address-d'ThesourceIPaddress[default:auto]'-rcomplete-ctrip-sI-linterface-d'Thenetworkinterface[default:auto]'-rcomplete-ctrip-si-lmin-round-duration-d'Theminimumdurationofeveryround[default:1s]'-rcomplete-ctrip-sT-lmax-round-duration-d'Themaximumdurationofeveryround[default:1s]'-rcomplete-ctrip-sg-lgrace-duration-d'TheperiodoftimetowaitforadditionalICMPresponsesafterthetargethasresponded[default:100ms]'-rcomplete-ctrip-linitial-sequence-d'Theinitialsequencenumber[default:33000]'-rcomplete-ctrip-sR-lmultipath-strategy-d'TheEqual-costMulti-Pathroutingstrategy(UDPonly)[default:classic]'-r-f-a"{classic'Thesrcordestportisusedtostorethesequencenumber',paris'TheUDP`checksum`fieldisusedtostorethesequencenumber',dublin'TheIP`identifier`fieldisusedtostorethesequencenumber'}"complete-ctrip-sU-lmax-inflight-d'Themaximumnumberofin-flightICMPechorequests[default:24]'-rcomplete-ctrip-sf-lfirst-ttl-d'TheTTLtostartfrom[default:1]'-rcomplete-ctrip-st-lmax-ttl-d'ThemaximumnumberofTTLhops[default:64]'-rcomplete-ctrip-lpacket-size-d'ThesizeofIPpackettosend(IPheader+ICMPheader+payload)[default:84]'-rcomplete-ctrip-lpayload-pattern-d'TherepeatingpatterninthepayloadoftheICMPpacket[default:0]'-rcomplete-ctrip-sQ-ltos-d'TheTOS(i.e.DSCP+ECN)IPheadervalue(TCPandUDPonly)[default:0]'-rcomplete-ctrip-lread-timeout-d'Thesocketreadtimeout[default:10ms]'-rcomplete-ctrip-sr-ldns-resolve-method-d'HowtoperformDNSqueries[default:system]'-r-f-a"{system'ResolveusingtheOSresolver',resolv'Resolveusingthe`/etc/resolv.conf`DNSconfiguration',google'ResolveusingtheGoogle`8.8.8.8`DNSservice',cloudflare'ResolveusingtheCloudflare`1.1.1.1`DNSservice'}"complete-ctrip-ldns-timeout-d'ThemaximumtimetowaittoperformDNSqueries[default:5s]'-rcomplete-ctrip-ss-lmax-samples-d'Themaximumnumberofsamplestorecordperhop[default:256]'-rcomplete-ctrip-lmax-flows-d'Themaximumnumberofflowstorecord[default:64]'-rcomplete-ctrip-sa-ltui-address-mode-d'Howtorenderaddresses[default:host]'-r-f-a"{ip'ShowIPaddressonly',host'Showreverse-lookupDNShostnameonly',both'ShowbothIPaddressandreverse-lookupDNShostname'}"complete-ctrip-ltui-as-mode-d'HowtorenderASinformation[default:asn]'-r-f-a"{asn'ShowtheASN',prefix'DisplaytheASprefix',country-code'Displaythecountrycode',registry'Displaytheregistryname',allocated'Displaytheallocateddate',name'DisplaytheASname'}"complete-ctrip-ltui-custom-columns-d'CustomcolumnstobedisplayedintheTUIhopstable[default:holsravbwdt]'-rcomplete-ctrip-ltui-icmp-extension-mode-d'HowtorenderICMPextensions[default:off]'-r-f-a"{off'Donotshow`icmp`extensions',mpls'ShowMPLSlabel(s)only',full'Showfull`icmp`extensiondataforallknownextensions',all'Showfull`icmp`extensiondataforallclasses'}"complete-ctrip-ltui-geoip-mode-d'HowtorenderGeoIpinformation[default:short]'-r-f-a"{off'DonotdisplayGeoIpdata',short'Showshortformat',long'Showlongformat',location'ShowlatitudeandLongitudeformat'}"complete-ctrip-sM-ltui-max-addrs-d'Themaximumnumberofaddressestoshowperhop[default:auto]'-rcomplete-ctrip-ltui-refresh-rate-d'TheTuirefreshrate[default:100ms]'-rcomplete-ctrip-ltui-privacy-max-ttl-d'Themaximumttlofhopswhichwillbemaskedforprivacy[default:0]'-rcomplete-ctrip-ltui-theme-colors-d'TheTUIthemecolors[item=color,item=color,..]'-rcomplete-ctrip-ltui-key-bindings-d'TheTUIkeybindings[command=key,command=key,..]'-rcomplete-ctrip-sC-lreport-cycles-d'Thenumberofreportcyclestorun[default:10]'-rcomplete-ctrip-sG-lgeoip-mmdb-file-d'ThesupportedMaxMindorIPinfoGeoIpmmdbfile'-r-Fcomplete-ctrip-lgenerate-d'Generateshellcompletion'-r-f-a"{bash'',elvish'',fish'',powershell'',zsh''}"complete-ctrip-llog-format-d'Thedebuglogformat[default:pretty]'-r-f-a"{compact'Displaylogdatainacompactformat',pretty'Displaylogdatainaprettyformat',json'Displaylogdatainajsonformat',chrome'DisplaylogdatainChrometraceformat'}"complete-ctrip-llog-filter-d'Thedebuglogfilter[default:trippy=debug]'-rcomplete-ctrip-llog-span-events-d'Thedebuglogformat[default:off]'-r-f-a"{off'Donotdisplayeventspans',active'Displayenterandexiteventspans',full'Displayalleventspans'}"complete-ctrip-su-lunprivileged-d'Tracewithoutrequiringelevatedprivilegesonsupportedplatforms[default:false]'complete-ctrip-ludp-d'TraceusingtheUDPprotocol'complete-ctrip-ltcp-d'TraceusingtheTCPprotocol'complete-ctrip-licmp-d'TraceusingtheICMPprotocol'complete-ctrip-s4-lipv4-d'UseIPv4only'complete-ctrip-s6-lipv6-d'UseIPv6only'complete-ctrip-se-licmp-extensions-d'ParseICMPextensions'complete-ctrip-sy-ldns-resolve-all-d'TracetoallIPsresolvedfromDNSlookup[default:false]'complete-ctrip-sz-ldns-lookup-as-info-d'Lookupautonomoussystem(AS)informationduringDNSqueries[default:false]'complete-ctrip-ltui-preserve-screen-d'Preservethescreenonexit[default:false]'complete-ctrip-lprint-tui-theme-items-d'PrintallTUIthemeitemsandexit'complete-ctrip-lprint-tui-binding-commands-d'PrintallTUIcommandsthatcanbeboundandexit'complete-ctrip-lgenerate-man-d'GenerateROFFmanpage'complete-ctrip-lprint-config-template-d'Printatemplatetomlconfigfileandexit'complete-ctrip-sv-lverbose-d'Enableverbosedebuglogging'complete-ctrip-sh-lhelp-d'Printhelp(seemorewith\'--help\')'complete-ctrip-sV-lversion-d'Printversion'
diff --git a/crates/trippy/tests/resources/snapshots/trip__print__tests__output@generate_man_page.snap b/crates/trippy-tui/tests/resources/snapshots/trippy_tui__print__tests__output@generate_man_page.snap
similarity index 99%
rename from crates/trippy/tests/resources/snapshots/trip__print__tests__output@generate_man_page.snap
rename to crates/trippy-tui/tests/resources/snapshots/trippy_tui__print__tests__output@generate_man_page.snap
index 1bcde09..3de03b1 100644
--- a/crates/trippy/tests/resources/snapshots/trip__print__tests__output@generate_man_page.snap
+++ b/crates/trippy-tui/tests/resources/snapshots/trippy_tui__print__tests__output@generate_man_page.snap
@@ -1,4 +1,4 @@
 ---
-source: crates/trippy/src/print.rs
+source: crates/trippy-tui/src/print.rs
 ---
 .ie\n(.g.dsAq\(aq.el.dsAq'.THtrip1"trip0.11.0-dev".SHNAMEtrip\-Anetworkdiagnostictool.SHSYNOPSIS\fBtrip\fR[\fB\-c\fR|\fB\-\-config\-file\fR][\fB\-m\fR|\fB\-\-mode\fR][\fB\-u\fR|\fB\-\-unprivileged\fR][\fB\-p\fR|\fB\-\-protocol\fR][\fB\-\-udp\fR][\fB\-\-tcp\fR][\fB\-\-icmp\fR][\fB\-F\fR|\fB\-\-addr\-family\fR][\fB\-4\fR|\fB\-\-ipv4\fR][\fB\-6\fR|\fB\-\-ipv6\fR][\fB\-P\fR|\fB\-\-target\-port\fR][\fB\-S\fR|\fB\-\-source\-port\fR][\fB\-A\fR|\fB\-\-source\-address\fR][\fB\-I\fR|\fB\-\-interface\fR][\fB\-i\fR|\fB\-\-min\-round\-duration\fR][\fB\-T\fR|\fB\-\-max\-round\-duration\fR][\fB\-g\fR|\fB\-\-grace\-duration\fR][\fB\-\-initial\-sequence\fR][\fB\-R\fR|\fB\-\-multipath\-strategy\fR][\fB\-U\fR|\fB\-\-max\-inflight\fR][\fB\-f\fR|\fB\-\-first\-ttl\fR][\fB\-t\fR|\fB\-\-max\-ttl\fR][\fB\-\-packet\-size\fR][\fB\-\-payload\-pattern\fR][\fB\-Q\fR|\fB\-\-tos\fR][\fB\-e\fR|\fB\-\-icmp\-extensions\fR][\fB\-\-read\-timeout\fR][\fB\-r\fR|\fB\-\-dns\-resolve\-method\fR][\fB\-y\fR|\fB\-\-dns\-resolve\-all\fR][\fB\-\-dns\-timeout\fR][\fB\-z\fR|\fB\-\-dns\-lookup\-as\-info\fR][\fB\-s\fR|\fB\-\-max\-samples\fR][\fB\-\-max\-flows\fR][\fB\-a\fR|\fB\-\-tui\-address\-mode\fR][\fB\-\-tui\-as\-mode\fR][\fB\-\-tui\-custom\-columns\fR][\fB\-\-tui\-icmp\-extension\-mode\fR][\fB\-\-tui\-geoip\-mode\fR][\fB\-M\fR|\fB\-\-tui\-max\-addrs\fR][\fB\-\-tui\-preserve\-screen\fR][\fB\-\-tui\-refresh\-rate\fR][\fB\-\-tui\-privacy\-max\-ttl\fR][\fB\-\-tui\-theme\-colors\fR][\fB\-\-print\-tui\-theme\-items\fR][\fB\-\-tui\-key\-bindings\fR][\fB\-\-print\-tui\-binding\-commands\fR][\fB\-C\fR|\fB\-\-report\-cycles\fR][\fB\-G\fR|\fB\-\-geoip\-mmdb\-file\fR][\fB\-\-generate\fR][\fB\-\-generate\-man\fR][\fB\-\-print\-config\-template\fR][\fB\-\-log\-format\fR][\fB\-\-log\-filter\fR][\fB\-\-log\-span\-events\fR][\fB\-v\fR|\fB\-\-verbose\fR][\fB\-h\fR|\fB\-\-help\fR][\fB\-V\fR|\fB\-\-version\fR][\fITARGETS\fR].SHDESCRIPTIONAnetworkdiagnostictool.SHOPTIONS.TP\fB\-c\fR,\fB\-\-config\-file\fR=\fICONFIG_FILE\fRConfigfile.TP\fB\-m\fR,\fB\-\-mode\fR=\fIMODE\fROutputmode[default:tui].br.br\fIPossiblevalues:\fR.RS14.IP\(bu2tui:DisplayinteractiveTUI.IP\(bu2stream:Displayacontinuousstreamoftracingdata.IP\(bu2pretty:GenerateaprettytexttablereportforNcycles.IP\(bu2markdown:GenerateaMarkdowntexttablereportforNcycles.IP\(bu2csv:GenerateaCSVreportforNcycles.IP\(bu2json:GenerateaJSONreportforNcycles.IP\(bu2dot:GenerateaGraphvizDOTfileforNcycles.IP\(bu2flows:DisplayallflowsforNcycles.IP\(bu2silent:DonotgenerateanytracingoutputforNcycles.RE.TP\fB\-u\fR,\fB\-\-unprivileged\fRTracewithoutrequiringelevatedprivilegesonsupportedplatforms[default:false].TP\fB\-p\fR,\fB\-\-protocol\fR=\fIPROTOCOL\fRTracingprotocol[default:icmp].br.br\fIPossiblevalues:\fR.RS14.IP\(bu2icmp:InternetControlMessageProtocol.IP\(bu2udp:UserDatagramProtocol.IP\(bu2tcp:TransmissionControlProtocol.RE.TP\fB\-\-udp\fRTraceusingtheUDPprotocol.TP\fB\-\-tcp\fRTraceusingtheTCPprotocol.TP\fB\-\-icmp\fRTraceusingtheICMPprotocol.TP\fB\-F\fR,\fB\-\-addr\-family\fR=\fIADDR_FAMILY\fRTheaddressfamily[default:Ipv4thenIpv6].br.br\fIPossiblevalues:\fR.RS14.IP\(bu2ipv4:Ipv4only.IP\(bu2ipv6:Ipv6only.IP\(bu2ipv6\-then\-ipv4:Ipv6withafallbacktoIpv4.IP\(bu2ipv4\-then\-ipv6:Ipv4withafallbacktoIpv6.RE.TP\fB\-4\fR,\fB\-\-ipv4\fRUseIPv4only.TP\fB\-6\fR,\fB\-\-ipv6\fRUseIPv6only.TP\fB\-P\fR,\fB\-\-target\-port\fR=\fITARGET_PORT\fRThetargetport(TCP&UDPonly)[default:80].TP\fB\-S\fR,\fB\-\-source\-port\fR=\fISOURCE_PORT\fRThesourceport(TCP&UDPonly)[default:auto].TP\fB\-A\fR,\fB\-\-source\-address\fR=\fISOURCE_ADDRESS\fRThesourceIPaddress[default:auto].TP\fB\-I\fR,\fB\-\-interface\fR=\fIINTERFACE\fRThenetworkinterface[default:auto].TP\fB\-i\fR,\fB\-\-min\-round\-duration\fR=\fIMIN_ROUND_DURATION\fRTheminimumdurationofeveryround[default:1s].TP\fB\-T\fR,\fB\-\-max\-round\-duration\fR=\fIMAX_ROUND_DURATION\fRThemaximumdurationofeveryround[default:1s].TP\fB\-g\fR,\fB\-\-grace\-duration\fR=\fIGRACE_DURATION\fRTheperiodoftimetowaitforadditionalICMPresponsesafterthetargethasresponded[default:100ms].TP\fB\-\-initial\-sequence\fR=\fIINITIAL_SEQUENCE\fRTheinitialsequencenumber[default:33000].TP\fB\-R\fR,\fB\-\-multipath\-strategy\fR=\fIMULTIPATH_STRATEGY\fRTheEqual\-costMulti\-Pathroutingstrategy(UDPonly)[default:classic].br.br\fIPossiblevalues:\fR.RS14.IP\(bu2classic:Thesrcordestportisusedtostorethesequencenumber.IP\(bu2paris:TheUDP`checksum`fieldisusedtostorethesequencenumber.IP\(bu2dublin:TheIP`identifier`fieldisusedtostorethesequencenumber.RE.TP\fB\-U\fR,\fB\-\-max\-inflight\fR=\fIMAX_INFLIGHT\fRThemaximumnumberofin\-flightICMPechorequests[default:24].TP\fB\-f\fR,\fB\-\-first\-ttl\fR=\fIFIRST_TTL\fRTheTTLtostartfrom[default:1].TP\fB\-t\fR,\fB\-\-max\-ttl\fR=\fIMAX_TTL\fRThemaximumnumberofTTLhops[default:64].TP\fB\-\-packet\-size\fR=\fIPACKET_SIZE\fRThesizeofIPpackettosend(IPheader+ICMPheader+payload)[default:84].TP\fB\-\-payload\-pattern\fR=\fIPAYLOAD_PATTERN\fRTherepeatingpatterninthepayloadoftheICMPpacket[default:0].TP\fB\-Q\fR,\fB\-\-tos\fR=\fITOS\fRTheTOS(i.e.DSCP+ECN)IPheadervalue(TCPandUDPonly)[default:0].TP\fB\-e\fR,\fB\-\-icmp\-extensions\fRParseICMPextensions.TP\fB\-\-read\-timeout\fR=\fIREAD_TIMEOUT\fRThesocketreadtimeout[default:10ms].TP\fB\-r\fR,\fB\-\-dns\-resolve\-method\fR=\fIDNS_RESOLVE_METHOD\fRHowtoperformDNSqueries[default:system].br.br\fIPossiblevalues:\fR.RS14.IP\(bu2system:ResolveusingtheOSresolver.IP\(bu2resolv:Resolveusingthe`/etc/resolv.conf`DNSconfiguration.IP\(bu2google:ResolveusingtheGoogle`8.8.8.8`DNSservice.IP\(bu2cloudflare:ResolveusingtheCloudflare`1.1.1.1`DNSservice.RE.TP\fB\-y\fR,\fB\-\-dns\-resolve\-all\fRTracetoallIPsresolvedfromDNSlookup[default:false].TP\fB\-\-dns\-timeout\fR=\fIDNS_TIMEOUT\fRThemaximumtimetowaittoperformDNSqueries[default:5s].TP\fB\-z\fR,\fB\-\-dns\-lookup\-as\-info\fRLookupautonomoussystem(AS)informationduringDNSqueries[default:false].TP\fB\-s\fR,\fB\-\-max\-samples\fR=\fIMAX_SAMPLES\fRThemaximumnumberofsamplestorecordperhop[default:256].TP\fB\-\-max\-flows\fR=\fIMAX_FLOWS\fRThemaximumnumberofflowstorecord[default:64].TP\fB\-a\fR,\fB\-\-tui\-address\-mode\fR=\fITUI_ADDRESS_MODE\fRHowtorenderaddresses[default:host].br.br\fIPossiblevalues:\fR.RS14.IP\(bu2ip:ShowIPaddressonly.IP\(bu2host:Showreverse\-lookupDNShostnameonly.IP\(bu2both:ShowbothIPaddressandreverse\-lookupDNShostname.RE.TP\fB\-\-tui\-as\-mode\fR=\fITUI_AS_MODE\fRHowtorenderASinformation[default:asn].br.br\fIPossiblevalues:\fR.RS14.IP\(bu2asn:ShowtheASN.IP\(bu2prefix:DisplaytheASprefix.IP\(bu2country\-code:Displaythecountrycode.IP\(bu2registry:Displaytheregistryname.IP\(bu2allocated:Displaytheallocateddate.IP\(bu2name:DisplaytheASname.RE.TP\fB\-\-tui\-custom\-columns\fR=\fITUI_CUSTOM_COLUMNS\fRCustomcolumnstobedisplayedintheTUIhopstable[default:holsravbwdt].TP\fB\-\-tui\-icmp\-extension\-mode\fR=\fITUI_ICMP_EXTENSION_MODE\fRHowtorenderICMPextensions[default:off].br.br\fIPossiblevalues:\fR.RS14.IP\(bu2off:Donotshow`icmp`extensions.IP\(bu2mpls:ShowMPLSlabel(s)only.IP\(bu2full:Showfull`icmp`extensiondataforallknownextensions.IP\(bu2all:Showfull`icmp`extensiondataforallclasses.RE.TP\fB\-\-tui\-geoip\-mode\fR=\fITUI_GEOIP_MODE\fRHowtorenderGeoIpinformation[default:short].br.br\fIPossiblevalues:\fR.RS14.IP\(bu2off:DonotdisplayGeoIpdata.IP\(bu2short:Showshortformat.IP\(bu2long:Showlongformat.IP\(bu2location:ShowlatitudeandLongitudeformat.RE.TP\fB\-M\fR,\fB\-\-tui\-max\-addrs\fR=\fITUI_MAX_ADDRS\fRThemaximumnumberofaddressestoshowperhop[default:auto].TP\fB\-\-tui\-preserve\-screen\fRPreservethescreenonexit[default:false].TP\fB\-\-tui\-refresh\-rate\fR=\fITUI_REFRESH_RATE\fRTheTuirefreshrate[default:100ms].TP\fB\-\-tui\-privacy\-max\-ttl\fR=\fITUI_PRIVACY_MAX_TTL\fRThemaximumttlofhopswhichwillbemaskedforprivacy[default:0].TP\fB\-\-tui\-theme\-colors\fR=\fITUI_THEME_COLORS\fRTheTUIthemecolors[item=color,item=color,..].TP\fB\-\-print\-tui\-theme\-items\fRPrintallTUIthemeitemsandexit.TP\fB\-\-tui\-key\-bindings\fR=\fITUI_KEY_BINDINGS\fRTheTUIkeybindings[command=key,command=key,..].TP\fB\-\-print\-tui\-binding\-commands\fRPrintallTUIcommandsthatcanbeboundandexit.TP\fB\-C\fR,\fB\-\-report\-cycles\fR=\fIREPORT_CYCLES\fRThenumberofreportcyclestorun[default:10].TP\fB\-G\fR,\fB\-\-geoip\-mmdb\-file\fR=\fIGEOIP_MMDB_FILE\fRThesupportedMaxMindorIPinfoGeoIpmmdbfile.TP\fB\-\-generate\fR=\fIGENERATE\fRGenerateshellcompletion.br.br[\fIpossiblevalues:\fRbash,elvish,fish,powershell,zsh].TP\fB\-\-generate\-man\fRGenerateROFFmanpage.TP\fB\-\-print\-config\-template\fRPrintatemplatetomlconfigfileandexit.TP\fB\-\-log\-format\fR=\fILOG_FORMAT\fRThedebuglogformat[default:pretty].br.br\fIPossiblevalues:\fR.RS14.IP\(bu2compact:Displaylogdatainacompactformat.IP\(bu2pretty:Displaylogdatainaprettyformat.IP\(bu2json:Displaylogdatainajsonformat.IP\(bu2chrome:DisplaylogdatainChrometraceformat.RE.TP\fB\-\-log\-filter\fR=\fILOG_FILTER\fRThedebuglogfilter[default:trippy=debug].TP\fB\-\-log\-span\-events\fR=\fILOG_SPAN_EVENTS\fRThedebuglogformat[default:off].br.br\fIPossiblevalues:\fR.RS14.IP\(bu2off:Donotdisplayeventspans.IP\(bu2active:Displayenterandexiteventspans.IP\(bu2full:Displayalleventspans.RE.TP\fB\-v\fR,\fB\-\-verbose\fREnableverbosedebuglogging.TP\fB\-h\fR,\fB\-\-help\fRPrinthelp(seeasummarywith\*(Aq\-h\*(Aq).TP\fB\-V\fR,\fB\-\-version\fRPrintversion.TP[\fITARGETS\fR]AspacedelimitedlistofhostnamesandIPstotrace.SHVERSIONv0.11.0\-dev.SHAUTHORSFujiApple<fujiapple852@gmail.com>
diff --git a/crates/trippy/tests/resources/snapshots/trip__print__tests__output@generate_powershell_shell_completions.snap b/crates/trippy-tui/tests/resources/snapshots/trippy_tui__print__tests__output@generate_powershell_shell_completions.snap
similarity index 99%
rename from crates/trippy/tests/resources/snapshots/trip__print__tests__output@generate_powershell_shell_completions.snap
rename to crates/trippy-tui/tests/resources/snapshots/trippy_tui__print__tests__output@generate_powershell_shell_completions.snap
index 4f4f2c2..532b688 100644
--- a/crates/trippy/tests/resources/snapshots/trip__print__tests__output@generate_powershell_shell_completions.snap
+++ b/crates/trippy-tui/tests/resources/snapshots/trippy_tui__print__tests__output@generate_powershell_shell_completions.snap
@@ -1,4 +1,4 @@
 ---
-source: crates/trippy/src/print.rs
+source: crates/trippy-tui/src/print.rs
 ---
 usingnamespaceSystem.Management.AutomationusingnamespaceSystem.Management.Automation.LanguageRegister-ArgumentCompleter-Native-CommandName'trip'-ScriptBlock{param($wordToComplete,$commandAst,$cursorPosition)$commandElements=$commandAst.CommandElements$command=@('trip'for($i=1;$i-lt$commandElements.Count;$i++){$element=$commandElements[$i]if($element-isnot[StringConstantExpressionAst]-or$element.StringConstantType-ne[StringConstantType]::BareWord-or$element.Value.StartsWith('-')-or$element.Value-eq$wordToComplete){break}$element.Value})-join';'$completions=@(switch($command){'trip'{[CompletionResult]::new('-c','c',[CompletionResultType]::ParameterName,'Configfile')[CompletionResult]::new('--config-file','config-file',[CompletionResultType]::ParameterName,'Configfile')[CompletionResult]::new('-m','m',[CompletionResultType]::ParameterName,'Outputmode[default:tui]')[CompletionResult]::new('--mode','mode',[CompletionResultType]::ParameterName,'Outputmode[default:tui]')[CompletionResult]::new('-p','p',[CompletionResultType]::ParameterName,'Tracingprotocol[default:icmp]')[CompletionResult]::new('--protocol','protocol',[CompletionResultType]::ParameterName,'Tracingprotocol[default:icmp]')[CompletionResult]::new('-F','F',[CompletionResultType]::ParameterName,'Theaddressfamily[default:Ipv4thenIpv6]')[CompletionResult]::new('--addr-family','addr-family',[CompletionResultType]::ParameterName,'Theaddressfamily[default:Ipv4thenIpv6]')[CompletionResult]::new('-P','P',[CompletionResultType]::ParameterName,'Thetargetport(TCP&UDPonly)[default:80]')[CompletionResult]::new('--target-port','target-port',[CompletionResultType]::ParameterName,'Thetargetport(TCP&UDPonly)[default:80]')[CompletionResult]::new('-S','S',[CompletionResultType]::ParameterName,'Thesourceport(TCP&UDPonly)[default:auto]')[CompletionResult]::new('--source-port','source-port',[CompletionResultType]::ParameterName,'Thesourceport(TCP&UDPonly)[default:auto]')[CompletionResult]::new('-A','A',[CompletionResultType]::ParameterName,'ThesourceIPaddress[default:auto]')[CompletionResult]::new('--source-address','source-address',[CompletionResultType]::ParameterName,'ThesourceIPaddress[default:auto]')[CompletionResult]::new('-I','I',[CompletionResultType]::ParameterName,'Thenetworkinterface[default:auto]')[CompletionResult]::new('--interface','interface',[CompletionResultType]::ParameterName,'Thenetworkinterface[default:auto]')[CompletionResult]::new('-i','i',[CompletionResultType]::ParameterName,'Theminimumdurationofeveryround[default:1s]')[CompletionResult]::new('--min-round-duration','min-round-duration',[CompletionResultType]::ParameterName,'Theminimumdurationofeveryround[default:1s]')[CompletionResult]::new('-T','T',[CompletionResultType]::ParameterName,'Themaximumdurationofeveryround[default:1s]')[CompletionResult]::new('--max-round-duration','max-round-duration',[CompletionResultType]::ParameterName,'Themaximumdurationofeveryround[default:1s]')[CompletionResult]::new('-g','g',[CompletionResultType]::ParameterName,'TheperiodoftimetowaitforadditionalICMPresponsesafterthetargethasresponded[default:100ms]')[CompletionResult]::new('--grace-duration','grace-duration',[CompletionResultType]::ParameterName,'TheperiodoftimetowaitforadditionalICMPresponsesafterthetargethasresponded[default:100ms]')[CompletionResult]::new('--initial-sequence','initial-sequence',[CompletionResultType]::ParameterName,'Theinitialsequencenumber[default:33000]')[CompletionResult]::new('-R','R',[CompletionResultType]::ParameterName,'TheEqual-costMulti-Pathroutingstrategy(UDPonly)[default:classic]')[CompletionResult]::new('--multipath-strategy','multipath-strategy',[CompletionResultType]::ParameterName,'TheEqual-costMulti-Pathroutingstrategy(UDPonly)[default:classic]')[CompletionResult]::new('-U','U',[CompletionResultType]::ParameterName,'Themaximumnumberofin-flightICMPechorequests[default:24]')[CompletionResult]::new('--max-inflight','max-inflight',[CompletionResultType]::ParameterName,'Themaximumnumberofin-flightICMPechorequests[default:24]')[CompletionResult]::new('-f','f',[CompletionResultType]::ParameterName,'TheTTLtostartfrom[default:1]')[CompletionResult]::new('--first-ttl','first-ttl',[CompletionResultType]::ParameterName,'TheTTLtostartfrom[default:1]')[CompletionResult]::new('-t','t',[CompletionResultType]::ParameterName,'ThemaximumnumberofTTLhops[default:64]')[CompletionResult]::new('--max-ttl','max-ttl',[CompletionResultType]::ParameterName,'ThemaximumnumberofTTLhops[default:64]')[CompletionResult]::new('--packet-size','packet-size',[CompletionResultType]::ParameterName,'ThesizeofIPpackettosend(IPheader+ICMPheader+payload)[default:84]')[CompletionResult]::new('--payload-pattern','payload-pattern',[CompletionResultType]::ParameterName,'TherepeatingpatterninthepayloadoftheICMPpacket[default:0]')[CompletionResult]::new('-Q','Q',[CompletionResultType]::ParameterName,'TheTOS(i.e.DSCP+ECN)IPheadervalue(TCPandUDPonly)[default:0]')[CompletionResult]::new('--tos','tos',[CompletionResultType]::ParameterName,'TheTOS(i.e.DSCP+ECN)IPheadervalue(TCPandUDPonly)[default:0]')[CompletionResult]::new('--read-timeout','read-timeout',[CompletionResultType]::ParameterName,'Thesocketreadtimeout[default:10ms]')[CompletionResult]::new('-r','r',[CompletionResultType]::ParameterName,'HowtoperformDNSqueries[default:system]')[CompletionResult]::new('--dns-resolve-method','dns-resolve-method',[CompletionResultType]::ParameterName,'HowtoperformDNSqueries[default:system]')[CompletionResult]::new('--dns-timeout','dns-timeout',[CompletionResultType]::ParameterName,'ThemaximumtimetowaittoperformDNSqueries[default:5s]')[CompletionResult]::new('-s','s',[CompletionResultType]::ParameterName,'Themaximumnumberofsamplestorecordperhop[default:256]')[CompletionResult]::new('--max-samples','max-samples',[CompletionResultType]::ParameterName,'Themaximumnumberofsamplestorecordperhop[default:256]')[CompletionResult]::new('--max-flows','max-flows',[CompletionResultType]::ParameterName,'Themaximumnumberofflowstorecord[default:64]')[CompletionResult]::new('-a','a',[CompletionResultType]::ParameterName,'Howtorenderaddresses[default:host]')[CompletionResult]::new('--tui-address-mode','tui-address-mode',[CompletionResultType]::ParameterName,'Howtorenderaddresses[default:host]')[CompletionResult]::new('--tui-as-mode','tui-as-mode',[CompletionResultType]::ParameterName,'HowtorenderASinformation[default:asn]')[CompletionResult]::new('--tui-custom-columns','tui-custom-columns',[CompletionResultType]::ParameterName,'CustomcolumnstobedisplayedintheTUIhopstable[default:holsravbwdt]')[CompletionResult]::new('--tui-icmp-extension-mode','tui-icmp-extension-mode',[CompletionResultType]::ParameterName,'HowtorenderICMPextensions[default:off]')[CompletionResult]::new('--tui-geoip-mode','tui-geoip-mode',[CompletionResultType]::ParameterName,'HowtorenderGeoIpinformation[default:short]')[CompletionResult]::new('-M','M',[CompletionResultType]::ParameterName,'Themaximumnumberofaddressestoshowperhop[default:auto]')[CompletionResult]::new('--tui-max-addrs','tui-max-addrs',[CompletionResultType]::ParameterName,'Themaximumnumberofaddressestoshowperhop[default:auto]')[CompletionResult]::new('--tui-refresh-rate','tui-refresh-rate',[CompletionResultType]::ParameterName,'TheTuirefreshrate[default:100ms]')[CompletionResult]::new('--tui-privacy-max-ttl','tui-privacy-max-ttl',[CompletionResultType]::ParameterName,'Themaximumttlofhopswhichwillbemaskedforprivacy[default:0]')[CompletionResult]::new('--tui-theme-colors','tui-theme-colors',[CompletionResultType]::ParameterName,'TheTUIthemecolors[item=color,item=color,..]')[CompletionResult]::new('--tui-key-bindings','tui-key-bindings',[CompletionResultType]::ParameterName,'TheTUIkeybindings[command=key,command=key,..]')[CompletionResult]::new('-C','C',[CompletionResultType]::ParameterName,'Thenumberofreportcyclestorun[default:10]')[CompletionResult]::new('--report-cycles','report-cycles',[CompletionResultType]::ParameterName,'Thenumberofreportcyclestorun[default:10]')[CompletionResult]::new('-G','G',[CompletionResultType]::ParameterName,'ThesupportedMaxMindorIPinfoGeoIpmmdbfile')[CompletionResult]::new('--geoip-mmdb-file','geoip-mmdb-file',[CompletionResultType]::ParameterName,'ThesupportedMaxMindorIPinfoGeoIpmmdbfile')[CompletionResult]::new('--generate','generate',[CompletionResultType]::ParameterName,'Generateshellcompletion')[CompletionResult]::new('--log-format','log-format',[CompletionResultType]::ParameterName,'Thedebuglogformat[default:pretty]')[CompletionResult]::new('--log-filter','log-filter',[CompletionResultType]::ParameterName,'Thedebuglogfilter[default:trippy=debug]')[CompletionResult]::new('--log-span-events','log-span-events',[CompletionResultType]::ParameterName,'Thedebuglogformat[default:off]')[CompletionResult]::new('-u','u',[CompletionResultType]::ParameterName,'Tracewithoutrequiringelevatedprivilegesonsupportedplatforms[default:false]')[CompletionResult]::new('--unprivileged','unprivileged',[CompletionResultType]::ParameterName,'Tracewithoutrequiringelevatedprivilegesonsupportedplatforms[default:false]')[CompletionResult]::new('--udp','udp',[CompletionResultType]::ParameterName,'TraceusingtheUDPprotocol')[CompletionResult]::new('--tcp','tcp',[CompletionResultType]::ParameterName,'TraceusingtheTCPprotocol')[CompletionResult]::new('--icmp','icmp',[CompletionResultType]::ParameterName,'TraceusingtheICMPprotocol')[CompletionResult]::new('-4','4',[CompletionResultType]::ParameterName,'UseIPv4only')[CompletionResult]::new('--ipv4','ipv4',[CompletionResultType]::ParameterName,'UseIPv4only')[CompletionResult]::new('-6','6',[CompletionResultType]::ParameterName,'UseIPv6only')[CompletionResult]::new('--ipv6','ipv6',[CompletionResultType]::ParameterName,'UseIPv6only')[CompletionResult]::new('-e','e',[CompletionResultType]::ParameterName,'ParseICMPextensions')[CompletionResult]::new('--icmp-extensions','icmp-extensions',[CompletionResultType]::ParameterName,'ParseICMPextensions')[CompletionResult]::new('-y','y',[CompletionResultType]::ParameterName,'TracetoallIPsresolvedfromDNSlookup[default:false]')[CompletionResult]::new('--dns-resolve-all','dns-resolve-all',[CompletionResultType]::ParameterName,'TracetoallIPsresolvedfromDNSlookup[default:false]')[CompletionResult]::new('-z','z',[CompletionResultType]::ParameterName,'Lookupautonomoussystem(AS)informationduringDNSqueries[default:false]')[CompletionResult]::new('--dns-lookup-as-info','dns-lookup-as-info',[CompletionResultType]::ParameterName,'Lookupautonomoussystem(AS)informationduringDNSqueries[default:false]')[CompletionResult]::new('--tui-preserve-screen','tui-preserve-screen',[CompletionResultType]::ParameterName,'Preservethescreenonexit[default:false]')[CompletionResult]::new('--print-tui-theme-items','print-tui-theme-items',[CompletionResultType]::ParameterName,'PrintallTUIthemeitemsandexit')[CompletionResult]::new('--print-tui-binding-commands','print-tui-binding-commands',[CompletionResultType]::ParameterName,'PrintallTUIcommandsthatcanbeboundandexit')[CompletionResult]::new('--generate-man','generate-man',[CompletionResultType]::ParameterName,'GenerateROFFmanpage')[CompletionResult]::new('--print-config-template','print-config-template',[CompletionResultType]::ParameterName,'Printatemplatetomlconfigfileandexit')[CompletionResult]::new('-v','v',[CompletionResultType]::ParameterName,'Enableverbosedebuglogging')[CompletionResult]::new('--verbose','verbose',[CompletionResultType]::ParameterName,'Enableverbosedebuglogging')[CompletionResult]::new('-h','h',[CompletionResultType]::ParameterName,'Printhelp(seemorewith''--help'')')[CompletionResult]::new('--help','help',[CompletionResultType]::ParameterName,'Printhelp(seemorewith''--help'')')[CompletionResult]::new('-V','V',[CompletionResultType]::ParameterName,'Printversion')[CompletionResult]::new('--version','version',[CompletionResultType]::ParameterName,'Printversion')break}})$completions.Where{$_.CompletionText-like"$wordToComplete*"}|Sort-Object-PropertyListItemText}
diff --git a/crates/trippy/tests/resources/snapshots/trip__print__tests__output@generate_zsh_shell_completions.snap b/crates/trippy-tui/tests/resources/snapshots/trippy_tui__print__tests__output@generate_zsh_shell_completions.snap
similarity index 99%
rename from crates/trippy/tests/resources/snapshots/trip__print__tests__output@generate_zsh_shell_completions.snap
rename to crates/trippy-tui/tests/resources/snapshots/trippy_tui__print__tests__output@generate_zsh_shell_completions.snap
index 19165ad..24bda3c 100644
--- a/crates/trippy/tests/resources/snapshots/trip__print__tests__output@generate_zsh_shell_completions.snap
+++ b/crates/trippy-tui/tests/resources/snapshots/trippy_tui__print__tests__output@generate_zsh_shell_completions.snap
@@ -1,4 +1,4 @@
 ---
-source: crates/trippy/src/print.rs
+source: crates/trippy-tui/src/print.rs
 ---
 #compdeftripautoload-Uis-at-least_trip(){typeset-Aopt_argstypeset-a_arguments_optionslocalret=1ifis-at-least5.2;then_arguments_options=(-s-S-C)else_arguments_options=(-s-C)filocalcontextcurcontext="$curcontext"stateline_arguments"${_arguments_options[@]}":\'-c+[Configfile]:CONFIG_FILE:_files'\'--config-file=[Configfile]:CONFIG_FILE:_files'\'-m+[Outputmode\[default\:tui\]]:MODE:((tui\:"DisplayinteractiveTUI"stream\:"Displayacontinuousstreamoftracingdata"pretty\:"GenerateaprettytexttablereportforNcycles"markdown\:"GenerateaMarkdowntexttablereportforNcycles"csv\:"GenerateaCSVreportforNcycles"json\:"GenerateaJSONreportforNcycles"dot\:"GenerateaGraphvizDOTfileforNcycles"flows\:"DisplayallflowsforNcycles"silent\:"DonotgenerateanytracingoutputforNcycles"))'\'--mode=[Outputmode\[default\:tui\]]:MODE:((tui\:"DisplayinteractiveTUI"stream\:"Displayacontinuousstreamoftracingdata"pretty\:"GenerateaprettytexttablereportforNcycles"markdown\:"GenerateaMarkdowntexttablereportforNcycles"csv\:"GenerateaCSVreportforNcycles"json\:"GenerateaJSONreportforNcycles"dot\:"GenerateaGraphvizDOTfileforNcycles"flows\:"DisplayallflowsforNcycles"silent\:"DonotgenerateanytracingoutputforNcycles"))'\'-p+[Tracingprotocol\[default\:icmp\]]:PROTOCOL:((icmp\:"InternetControlMessageProtocol"udp\:"UserDatagramProtocol"tcp\:"TransmissionControlProtocol"))'\'--protocol=[Tracingprotocol\[default\:icmp\]]:PROTOCOL:((icmp\:"InternetControlMessageProtocol"udp\:"UserDatagramProtocol"tcp\:"TransmissionControlProtocol"))'\'-F+[Theaddressfamily\[default\:Ipv4thenIpv6\]]:ADDR_FAMILY:((ipv4\:"Ipv4only"ipv6\:"Ipv6only"ipv6-then-ipv4\:"Ipv6withafallbacktoIpv4"ipv4-then-ipv6\:"Ipv4withafallbacktoIpv6"))'\'--addr-family=[Theaddressfamily\[default\:Ipv4thenIpv6\]]:ADDR_FAMILY:((ipv4\:"Ipv4only"ipv6\:"Ipv6only"ipv6-then-ipv4\:"Ipv6withafallbacktoIpv4"ipv4-then-ipv6\:"Ipv4withafallbacktoIpv6"))'\'-P+[Thetargetport(TCP&UDPonly)\[default\:80\]]:TARGET_PORT:'\'--target-port=[Thetargetport(TCP&UDPonly)\[default\:80\]]:TARGET_PORT:'\'-S+[Thesourceport(TCP&UDPonly)\[default\:auto\]]:SOURCE_PORT:'\'--source-port=[Thesourceport(TCP&UDPonly)\[default\:auto\]]:SOURCE_PORT:'\'(-I--interface)-A+[ThesourceIPaddress\[default\:auto\]]:SOURCE_ADDRESS:'\'(-I--interface)--source-address=[ThesourceIPaddress\[default\:auto\]]:SOURCE_ADDRESS:'\'-I+[Thenetworkinterface\[default\:auto\]]:INTERFACE:'\'--interface=[Thenetworkinterface\[default\:auto\]]:INTERFACE:'\'-i+[Theminimumdurationofeveryround\[default\:1s\]]:MIN_ROUND_DURATION:'\'--min-round-duration=[Theminimumdurationofeveryround\[default\:1s\]]:MIN_ROUND_DURATION:'\'-T+[Themaximumdurationofeveryround\[default\:1s\]]:MAX_ROUND_DURATION:'\'--max-round-duration=[Themaximumdurationofeveryround\[default\:1s\]]:MAX_ROUND_DURATION:'\'-g+[TheperiodoftimetowaitforadditionalICMPresponsesafterthetargethasresponded\[default\:100ms\]]:GRACE_DURATION:'\'--grace-duration=[TheperiodoftimetowaitforadditionalICMPresponsesafterthetargethasresponded\[default\:100ms\]]:GRACE_DURATION:'\'--initial-sequence=[Theinitialsequencenumber\[default\:33000\]]:INITIAL_SEQUENCE:'\'-R+[TheEqual-costMulti-Pathroutingstrategy(UDPonly)\[default\:classic\]]:MULTIPATH_STRATEGY:((classic\:"Thesrcordestportisusedtostorethesequencenumber"paris\:"TheUDP\`checksum\`fieldisusedtostorethesequencenumber"dublin\:"TheIP\`identifier\`fieldisusedtostorethesequencenumber"))'\'--multipath-strategy=[TheEqual-costMulti-Pathroutingstrategy(UDPonly)\[default\:classic\]]:MULTIPATH_STRATEGY:((classic\:"Thesrcordestportisusedtostorethesequencenumber"paris\:"TheUDP\`checksum\`fieldisusedtostorethesequencenumber"dublin\:"TheIP\`identifier\`fieldisusedtostorethesequencenumber"))'\'-U+[Themaximumnumberofin-flightICMPechorequests\[default\:24\]]:MAX_INFLIGHT:'\'--max-inflight=[Themaximumnumberofin-flightICMPechorequests\[default\:24\]]:MAX_INFLIGHT:'\'-f+[TheTTLtostartfrom\[default\:1\]]:FIRST_TTL:'\'--first-ttl=[TheTTLtostartfrom\[default\:1\]]:FIRST_TTL:'\'-t+[ThemaximumnumberofTTLhops\[default\:64\]]:MAX_TTL:'\'--max-ttl=[ThemaximumnumberofTTLhops\[default\:64\]]:MAX_TTL:'\'--packet-size=[ThesizeofIPpackettosend(IPheader+ICMPheader+payload)\[default\:84\]]:PACKET_SIZE:'\'--payload-pattern=[TherepeatingpatterninthepayloadoftheICMPpacket\[default\:0\]]:PAYLOAD_PATTERN:'\'-Q+[TheTOS(i.e.DSCP+ECN)IPheadervalue(TCPandUDPonly)\[default\:0\]]:TOS:'\'--tos=[TheTOS(i.e.DSCP+ECN)IPheadervalue(TCPandUDPonly)\[default\:0\]]:TOS:'\'--read-timeout=[Thesocketreadtimeout\[default\:10ms\]]:READ_TIMEOUT:'\'-r+[HowtoperformDNSqueries\[default\:system\]]:DNS_RESOLVE_METHOD:((system\:"ResolveusingtheOSresolver"resolv\:"Resolveusingthe\`/etc/resolv.conf\`DNSconfiguration"google\:"ResolveusingtheGoogle\`8.8.8.8\`DNSservice"cloudflare\:"ResolveusingtheCloudflare\`1.1.1.1\`DNSservice"))'\'--dns-resolve-method=[HowtoperformDNSqueries\[default\:system\]]:DNS_RESOLVE_METHOD:((system\:"ResolveusingtheOSresolver"resolv\:"Resolveusingthe\`/etc/resolv.conf\`DNSconfiguration"google\:"ResolveusingtheGoogle\`8.8.8.8\`DNSservice"cloudflare\:"ResolveusingtheCloudflare\`1.1.1.1\`DNSservice"))'\'--dns-timeout=[ThemaximumtimetowaittoperformDNSqueries\[default\:5s\]]:DNS_TIMEOUT:'\'-s+[Themaximumnumberofsamplestorecordperhop\[default\:256\]]:MAX_SAMPLES:'\'--max-samples=[Themaximumnumberofsamplestorecordperhop\[default\:256\]]:MAX_SAMPLES:'\'--max-flows=[Themaximumnumberofflowstorecord\[default\:64\]]:MAX_FLOWS:'\'-a+[Howtorenderaddresses\[default\:host\]]:TUI_ADDRESS_MODE:((ip\:"ShowIPaddressonly"host\:"Showreverse-lookupDNShostnameonly"both\:"ShowbothIPaddressandreverse-lookupDNShostname"))'\'--tui-address-mode=[Howtorenderaddresses\[default\:host\]]:TUI_ADDRESS_MODE:((ip\:"ShowIPaddressonly"host\:"Showreverse-lookupDNShostnameonly"both\:"ShowbothIPaddressandreverse-lookupDNShostname"))'\'--tui-as-mode=[HowtorenderASinformation\[default\:asn\]]:TUI_AS_MODE:((asn\:"ShowtheASN"prefix\:"DisplaytheASprefix"country-code\:"Displaythecountrycode"registry\:"Displaytheregistryname"allocated\:"Displaytheallocateddate"name\:"DisplaytheASname"))'\'--tui-custom-columns=[CustomcolumnstobedisplayedintheTUIhopstable\[default\:holsravbwdt\]]:TUI_CUSTOM_COLUMNS:'\'--tui-icmp-extension-mode=[HowtorenderICMPextensions\[default\:off\]]:TUI_ICMP_EXTENSION_MODE:((off\:"Donotshow\`icmp\`extensions"mpls\:"ShowMPLSlabel(s)only"full\:"Showfull\`icmp\`extensiondataforallknownextensions"all\:"Showfull\`icmp\`extensiondataforallclasses"))'\'--tui-geoip-mode=[HowtorenderGeoIpinformation\[default\:short\]]:TUI_GEOIP_MODE:((off\:"DonotdisplayGeoIpdata"short\:"Showshortformat"long\:"Showlongformat"location\:"ShowlatitudeandLongitudeformat"))'\'-M+[Themaximumnumberofaddressestoshowperhop\[default\:auto\]]:TUI_MAX_ADDRS:'\'--tui-max-addrs=[Themaximumnumberofaddressestoshowperhop\[default\:auto\]]:TUI_MAX_ADDRS:'\'--tui-refresh-rate=[TheTuirefreshrate\[default\:100ms\]]:TUI_REFRESH_RATE:'\'--tui-privacy-max-ttl=[Themaximumttlofhopswhichwillbemaskedforprivacy\[default\:0\]]:TUI_PRIVACY_MAX_TTL:'\'*--tui-theme-colors=[TheTUIthemecolors\[item=color,item=color,..\]]:TUI_THEME_COLORS:'\'*--tui-key-bindings=[TheTUIkeybindings\[command=key,command=key,..\]]:TUI_KEY_BINDINGS:'\'-C+[Thenumberofreportcyclestorun\[default\:10\]]:REPORT_CYCLES:'\'--report-cycles=[Thenumberofreportcyclestorun\[default\:10\]]:REPORT_CYCLES:'\'-G+[ThesupportedMaxMindorIPinfoGeoIpmmdbfile]:GEOIP_MMDB_FILE:_files'\'--geoip-mmdb-file=[ThesupportedMaxMindorIPinfoGeoIpmmdbfile]:GEOIP_MMDB_FILE:_files'\'--generate=[Generateshellcompletion]:GENERATE:(bashelvishfishpowershellzsh)'\'--log-format=[Thedebuglogformat\[default\:pretty\]]:LOG_FORMAT:((compact\:"Displaylogdatainacompactformat"pretty\:"Displaylogdatainaprettyformat"json\:"Displaylogdatainajsonformat"chrome\:"DisplaylogdatainChrometraceformat"))'\'--log-filter=[Thedebuglogfilter\[default\:trippy=debug\]]:LOG_FILTER:'\'--log-span-events=[Thedebuglogformat\[default\:off\]]:LOG_SPAN_EVENTS:((off\:"Donotdisplayeventspans"active\:"Displayenterandexiteventspans"full\:"Displayalleventspans"))'\'-u[Tracewithoutrequiringelevatedprivilegesonsupportedplatforms\[default\:false\]]'\'--unprivileged[Tracewithoutrequiringelevatedprivilegesonsupportedplatforms\[default\:false\]]'\'(-p--protocol--tcp--icmp)--udp[TraceusingtheUDPprotocol]'\'(-p--protocol--udp--icmp)--tcp[TraceusingtheTCPprotocol]'\'(-p--protocol--udp--tcp)--icmp[TraceusingtheICMPprotocol]'\'(-6--ipv6-F--addr-family)-4[UseIPv4only]'\'(-6--ipv6-F--addr-family)--ipv4[UseIPv4only]'\'(-4--ipv4-F--addr-family)-6[UseIPv6only]'\'(-4--ipv4-F--addr-family)--ipv6[UseIPv6only]'\'-e[ParseICMPextensions]'\'--icmp-extensions[ParseICMPextensions]'\'-y[TracetoallIPsresolvedfromDNSlookup\[default\:false\]]'\'--dns-resolve-all[TracetoallIPsresolvedfromDNSlookup\[default\:false\]]'\'-z[Lookupautonomoussystem(AS)informationduringDNSqueries\[default\:false\]]'\'--dns-lookup-as-info[Lookupautonomoussystem(AS)informationduringDNSqueries\[default\:false\]]'\'--tui-preserve-screen[Preservethescreenonexit\[default\:false\]]'\'--print-tui-theme-items[PrintallTUIthemeitemsandexit]'\'--print-tui-binding-commands[PrintallTUIcommandsthatcanbeboundandexit]'\'--generate-man[GenerateROFFmanpage]'\'--print-config-template[Printatemplatetomlconfigfileandexit]'\'-v[Enableverbosedebuglogging]'\'--verbose[Enableverbosedebuglogging]'\'-h[Printhelp(seemorewith'\''--help'\'')]'\'--help[Printhelp(seemorewith'\''--help'\'')]'\'-V[Printversion]'\'--version[Printversion]'\'*::targets--AspacedelimitedlistofhostnamesandIPstotrace:'\&&ret=0}(($+functions[_trip_commands]))||_trip_commands(){localcommands;commands=()_describe-tcommands'tripcommands'commands"$@"}if["$funcstack[1]"="_trip"];then_trip"$@"elsecompdef_triptripfi
diff --git a/crates/trippy/tests/resources/snapshots/trip__print__tests__output@tui_binding_commands_match.snap b/crates/trippy-tui/tests/resources/snapshots/trippy_tui__print__tests__output@tui_binding_commands_match.snap
similarity index 92%
rename from crates/trippy/tests/resources/snapshots/trip__print__tests__output@tui_binding_commands_match.snap
rename to crates/trippy-tui/tests/resources/snapshots/trippy_tui__print__tests__output@tui_binding_commands_match.snap
index 777b36b..34d5183 100644
--- a/crates/trippy/tests/resources/snapshots/trip__print__tests__output@tui_binding_commands_match.snap
+++ b/crates/trippy-tui/tests/resources/snapshots/trippy_tui__print__tests__output@tui_binding_commands_match.snap
@@ -1,4 +1,4 @@
 ---
-source: crates/trippy/src/print.rs
+source: crates/trippy-tui/src/print.rs
 ---
 TUIbindingcommands:toggle-help,toggle-help-alt,toggle-settings,next-hop,previous-hop,next-trace,previous-trace,next-hop-address,previous-hop-address,address-mode-ip,address-mode-host,address-mode-both,toggle-freeze,toggle-chart,toggle-map,toggle-flows,toggle-privacy,expand-hosts,expand-hosts-max,contract-hosts,contract-hosts-min,chart-zoom-in,chart-zoom-out,clear-trace-data,clear-dns-cache,clear-selection,toggle-as-info,toggle-hop-details,quit
diff --git a/crates/trippy/tests/resources/snapshots/trip__print__tests__output@tui_theme_items_match.snap b/crates/trippy-tui/tests/resources/snapshots/trippy_tui__print__tests__output@tui_theme_items_match.snap
similarity index 95%
rename from crates/trippy/tests/resources/snapshots/trip__print__tests__output@tui_theme_items_match.snap
rename to crates/trippy-tui/tests/resources/snapshots/trippy_tui__print__tests__output@tui_theme_items_match.snap
index 0274e59..be092b8 100644
--- a/crates/trippy/tests/resources/snapshots/trip__print__tests__output@tui_theme_items_match.snap
+++ b/crates/trippy-tui/tests/resources/snapshots/trippy_tui__print__tests__output@tui_theme_items_match.snap
@@ -1,4 +1,4 @@
 ---
-source: crates/trippy/src/print.rs
+source: crates/trippy-tui/src/print.rs
 ---
 TUIthemecoloritems:bg-color,border-color,text-color,tab-text-color,hops-table-header-bg-color,hops-table-header-text-color,hops-table-row-active-text-color,hops-table-row-inactive-text-color,hops-chart-selected-color,hops-chart-unselected-color,hops-chart-axis-color,frequency-chart-bar-color,frequency-chart-text-color,flows-chart-bar-selected-color,flows-chart-bar-unselected-color,flows-chart-text-current-color,flows-chart-text-non-current-color,samples-chart-color,help-dialog-bg-color,help-dialog-text-color,settings-tab-text-color,settings-dialog-bg-color,settings-table-header-text-color,settings-table-header-bg-color,settings-table-row-text-color,map-world-color,map-radius-color,map-selected-color,map-info-panel-border-color,map-info-panel-bg-color,map-info-panel-text-color