diff --git a/helix-dap/src/client.rs b/helix-dap/src/client.rs
index 9208db9d..90ddeb2f 100644
--- a/helix-dap/src/client.rs
+++ b/helix-dap/src/client.rs
@@ -80,6 +80,7 @@ impl Client {
             //
             breakpoints: HashMap::new(),
             stack_frames: HashMap::new(),
+            thread_states: HashMap::new(),
             thread_id: None,
             active_frame: None,
             is_running: false,
diff --git a/helix-term/src/application.rs b/helix-term/src/application.rs
index eed7b914..527d374f 100644
--- a/helix-term/src/application.rs
+++ b/helix-term/src/application.rs
@@ -258,7 +258,7 @@ impl Application {
     pub async fn handle_debugger_message(&mut self, payload: helix_dap::Payload) {
         use crate::commands::dap::{resume_application, select_thread_id};
         use helix_dap::{events, Event};
-        let mut debugger = match self.editor.debugger.as_mut() {
+        let debugger = match self.editor.debugger.as_mut() {
             Some(debugger) => debugger,
             None => return,
         };
@@ -274,12 +274,12 @@ impl Application {
                     ..
                 }) => {
                     if let Some(thread_id) = thread_id {
-                        debugger.thread_states.insert(thread_id, reason); // TODO: dap uses "type" || "reason" here
+                        debugger.thread_states.insert(thread_id, reason.clone()); // TODO: dap uses "type" || "reason" here
+
                         // whichever thread stops is made "current" (if no previously selected thread).
                         select_thread_id(&mut self.editor, thread_id, false).await;
                     }
 
-
                     let scope = match thread_id {
                         Some(id) => format!("Thread {}", id),
                         None => "Target".to_owned(),
@@ -305,7 +305,7 @@ impl Application {
                     }
                 }
                 Event::Thread(_) => {
-                    // TODO: update thread_states, make threads request 
+                    // TODO: update thread_states, make threads request
                 }
                 Event::Output(events::Output {
                     category, output, ..
diff --git a/helix-term/src/commands/dap.rs b/helix-term/src/commands/dap.rs
index 37f87711..f40bdcbf 100644
--- a/helix-term/src/commands/dap.rs
+++ b/helix-term/src/commands/dap.rs
@@ -1,7 +1,7 @@
 use super::{align_view, Align, Context, Editor};
 use crate::ui::Picker;
 use helix_core::Selection;
-use helix_dap::Client;
+use helix_dap::{self as dap, Client};
 use helix_lsp::block_on;
 
 use serde_json::{to_value, Value};
@@ -20,7 +20,9 @@ pub fn dap_pos_to_pos(doc: &helix_core::Rope, line: usize, column: usize) -> Opt
 
 pub fn resume_application(debugger: &mut Client) {
     if let Some(thread_id) = debugger.thread_id {
-        debugger.thread_states.insert(thread_id, "running".to_string());
+        debugger
+            .thread_states
+            .insert(thread_id, "running".to_string());
         debugger.stack_frames.remove(&thread_id);
     }
     debugger.active_frame = None;
@@ -80,7 +82,32 @@ pub fn jump_to_stack_frame(editor: &mut Editor, frame: &helix_dap::StackFrame) {
     align_view(doc, view, Align::Center);
 }
 
-// DAP
+fn thread_picker(cx: &mut Context, callback_fn: impl Fn(&mut Editor, &dap::Thread) + 'static) {
+    let debugger = match &mut cx.editor.debugger {
+        Some(debugger) => debugger,
+        None => return,
+    };
+
+    let threads = match block_on(debugger.threads()) {
+        Ok(threads) => threads,
+        Err(e) => {
+            cx.editor
+                .set_error(format!("Failed to retrieve threads: {:?}", e));
+            return;
+        }
+    };
+
+    let picker = Picker::new(
+        true,
+        threads,
+        |thread| thread.name.clone().into(),
+        move |editor, thread, _action| callback_fn(editor, thread),
+    );
+    cx.push_layer(Box::new(picker))
+}
+
+// -- DAP
+
 pub fn dap_start_impl(
     editor: &mut Editor,
     name: Option<&str>,
@@ -312,23 +339,17 @@ pub fn dap_continue(cx: &mut Context) {
 }
 
 pub fn dap_pause(cx: &mut Context) {
-    let debugger = match &mut cx.editor.debugger {
+    thread_picker(cx, |editor, thread| {
+    let debugger = match &mut editor.debugger {
         Some(debugger) => debugger,
         None => return,
     };
-
-    // TODO: this should instead open a picker to pause a selected thread
-
-    if !debugger.is_running {
-        cx.editor.set_status("Debuggee is not running".to_owned());
-        return;
-    }
-
-    // FIXME: correct number here
-    let request = debugger.pause(0);
-    if let Err(e) = block_on(request) {
-        cx.editor.set_error(format!("Failed to pause: {:?}", e));
-    }
+        let request = debugger.pause(thread.id);
+        // NOTE: we don't need to set active thread id here because DAP will emit a "stopped" event
+        if let Err(e) = block_on(request) {
+            editor.set_error(format!("Failed to pause: {:?}", e));
+        }
+    })
 }
 
 pub fn dap_step_in(cx: &mut Context) {
@@ -456,28 +477,7 @@ pub fn dap_terminate(cx: &mut Context) {
 }
 
 pub fn dap_switch_thread(cx: &mut Context) {
-    let debugger = match &mut cx.editor.debugger {
-        Some(debugger) => debugger,
-        None => return,
-    };
-
-    let request = debugger.threads();
-    let threads = match block_on(request) {
-        Ok(threads) => threads,
-        Err(e) => {
-            cx.editor
-                .set_error(format!("Failed to retrieve threads: {:?}", e));
-            return;
-        }
-    };
-
-    let picker = Picker::new(
-        true,
-        threads,
-        |thread| thread.name.clone().into(),
-        |editor, thread, _action| {
-            block_on(select_thread_id(editor, thread.id, true));
-        },
-    );
-    cx.push_layer(Box::new(picker))
+    thread_picker(cx, |editor, thread| {
+        block_on(select_thread_id(editor, thread.id, true));
+    })
 }