diff --git a/atuin-client/src/settings.rs b/atuin-client/src/settings.rs
index 08715ca..ef6752f 100644
--- a/atuin-client/src/settings.rs
+++ b/atuin-client/src/settings.rs
@@ -41,9 +41,22 @@ impl From<Dialect> for chrono_english::Dialect {
     }
 }
 
+#[derive(Clone, Debug, Deserialize, Copy)]
+pub enum Style {
+    #[serde(rename = "auto")]
+    Auto,
+
+    #[serde(rename = "full")]
+    Full,
+
+    #[serde(rename = "compact")]
+    Compact,
+}
+
 #[derive(Clone, Debug, Deserialize)]
 pub struct Settings {
     pub dialect: Dialect,
+    pub style: Style,
     pub auto_sync: bool,
     pub sync_address: String,
     pub sync_frequency: String,
@@ -134,6 +147,7 @@ impl Settings {
             .set_default("sync_address", "https://api.atuin.sh")?
             .set_default("search_mode", "prefix")?
             .set_default("session_token", "")?
+            .set_default("style", "auto")?
             .add_source(Environment::with_prefix("atuin").separator("_"));
 
         config_builder = if config_file.exists() {
diff --git a/src/command/search.rs b/src/command/search.rs
index 6e7ec25..a28b154 100644
--- a/src/command/search.rs
+++ b/src/command/search.rs
@@ -86,6 +86,7 @@ impl State {
         &mut self,
         f: &mut tui::Frame<T>,
         r: tui::layout::Rect,
+        b: tui::widgets::Block,
     ) {
         let durations = self.durations();
         let max_length = durations.iter().fold(0, |largest, i| {
@@ -153,7 +154,7 @@ impl State {
             .collect();
 
         let results = List::new(results)
-            .block(Block::default().borders(Borders::ALL).title("History"))
+            .block(b)
             .start_corner(Corner::BottomLeft)
             .highlight_symbol(">> ");
 
@@ -321,9 +322,13 @@ fn draw<T: Backend>(f: &mut Frame<'_, T>, history_count: i64, app: &mut State) {
 
     f.render_widget(title, top_left_chunks[0]);
     f.render_widget(help, top_left_chunks[1]);
-
-    app.render_results(f, chunks[1]);
     f.render_widget(stats, top_right_chunks[0]);
+
+    app.render_results(
+        f,
+        chunks[1],
+        Block::default().borders(Borders::ALL).title("History"),
+    );
     f.render_widget(input, chunks[2]);
 
     f.set_cursor(
@@ -334,6 +339,70 @@ fn draw<T: Backend>(f: &mut Frame<'_, T>, history_count: i64, app: &mut State) {
     );
 }
 
+#[allow(clippy::cast_possible_truncation)]
+fn draw_compact<T: Backend>(f: &mut Frame<'_, T>, history_count: i64, app: &mut State) {
+    let chunks = Layout::default()
+        .direction(Direction::Vertical)
+        .margin(0)
+        .horizontal_margin(1)
+        .constraints(
+            [
+                Constraint::Length(1),
+                Constraint::Min(1),
+                Constraint::Length(1),
+            ]
+            .as_ref(),
+        )
+        .split(f.size());
+
+    let header_chunks = Layout::default()
+        .direction(Direction::Horizontal)
+        .constraints(
+            [
+                Constraint::Ratio(1, 3),
+                Constraint::Ratio(1, 3),
+                Constraint::Ratio(1, 3),
+            ]
+            .as_ref(),
+        )
+        .split(chunks[0]);
+
+    let title = Paragraph::new(Text::from(Span::styled(
+        format!("Atuin v{}", VERSION),
+        Style::default().fg(Color::DarkGray),
+    )));
+
+    let help = Paragraph::new(Text::from(Spans::from(vec![
+        Span::styled("Esc", Style::default().add_modifier(Modifier::BOLD)),
+        Span::raw(" to exit"),
+    ])))
+    .style(Style::default().fg(Color::DarkGray))
+    .alignment(Alignment::Center);
+
+    let stats = Paragraph::new(Text::from(Span::raw(format!(
+        "history count: {}",
+        history_count,
+    ))))
+    .style(Style::default().fg(Color::DarkGray))
+    .alignment(Alignment::Right);
+
+    let input = Paragraph::new(format!("] {}", app.input.clone())).block(Block::default());
+
+    f.render_widget(title, header_chunks[0]);
+    f.render_widget(help, header_chunks[1]);
+    f.render_widget(stats, header_chunks[2]);
+
+    app.render_results(f, chunks[1], Block::default());
+    f.render_widget(input, chunks[2]);
+
+    f.set_cursor(
+        // Put cursor past the end of the input text
+        chunks[2].x + app.input.width() as u16 + 2,
+        // Move one line down, from the border to the input line
+        chunks[2].y + 1,
+    );
+}
+
 // this is a big blob of horrible! clean it up!
 // for now, it works. But it'd be great if it were more easily readable, and
 // modular. I'd like to add some more stats and stuff at some point
@@ -341,6 +410,7 @@ fn draw<T: Backend>(f: &mut Frame<'_, T>, history_count: i64, app: &mut State) {
 async fn select_history(
     query: &[String],
     search_mode: SearchMode,
+    style: atuin_client::settings::Style,
     db: &mut (impl Database + Send + Sync),
 ) -> Result<String> {
     let stdout = stdout().into_raw_mode()?;
@@ -369,7 +439,18 @@ async fn select_history(
             }
         }
 
-        terminal.draw(|f| draw(f, history_count, &mut app))?;
+        let compact = match style {
+            atuin_client::settings::Style::Auto => {
+                terminal.size().map(|size| size.height < 14).unwrap_or(true)
+            }
+            atuin_client::settings::Style::Compact => true,
+            atuin_client::settings::Style::Full => false,
+        };
+        if compact {
+            terminal.draw(|f| draw_compact(f, history_count, &mut app))?;
+        } else {
+            terminal.draw(|f| draw(f, history_count, &mut app))?;
+        }
     }
 }
 
@@ -405,7 +486,7 @@ pub async fn run(
     };
 
     if interactive {
-        let item = select_history(query, settings.search_mode, db).await?;
+        let item = select_history(query, settings.search_mode, settings.style, db).await?;
         eprintln!("{}", item);
     } else {
         let results = db