diff --git a/Cargo.lock b/Cargo.lock
index bf01504e..e5ffee0b 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -324,7 +324,7 @@ dependencies = [
 
 [[package]]
 name = "helix-dap"
-version = "0.3.0"
+version = "0.4.0"
 dependencies = [
  "anyhow",
  "fern",
@@ -375,6 +375,7 @@ dependencies = [
  "futures-util",
  "fuzzy-matcher",
  "helix-core",
+ "helix-dap",
  "helix-lsp",
  "helix-tui",
  "helix-view",
@@ -416,6 +417,7 @@ dependencies = [
  "encoding_rs",
  "futures-util",
  "helix-core",
+ "helix-dap",
  "helix-lsp",
  "helix-tui",
  "log",
@@ -423,6 +425,7 @@ dependencies = [
  "serde",
  "slotmap",
  "tokio",
+ "tokio-stream",
  "toml",
  "url",
  "which",
diff --git a/helix-dap/Cargo.toml b/helix-dap/Cargo.toml
index ce1e2d16..7582067e 100644
--- a/helix-dap/Cargo.toml
+++ b/helix-dap/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "helix-dap"
-version = "0.3.0"
+version = "0.4.0"
 authors = ["Blaž Hrastnik <blaz@mxxn.io>"]
 edition = "2018"
 license = "MPL-2.0"
diff --git a/helix-dap/src/client.rs b/helix-dap/src/client.rs
index 0f23dd15..baf924b9 100644
--- a/helix-dap/src/client.rs
+++ b/helix-dap/src/client.rs
@@ -186,12 +186,12 @@ impl Client {
         &self,
         arguments: R::Arguments,
     ) -> Result<R::Result> {
-        let (callback_rx, mut callback_tx) = channel(1);
+        let (callback_tx, mut callback_rx) = channel(1);
 
         let arguments = Some(serde_json::to_value(arguments)?);
 
         let req = Request {
-            back_ch: Some(callback_rx),
+            back_ch: Some(callback_tx),
             seq: self.next_request_id(),
             command: R::COMMAND.to_string(),
             arguments,
@@ -201,7 +201,7 @@ impl Client {
             .send(req)
             .expect("Failed to send request to debugger");
 
-        let response = callback_tx.recv().await.unwrap()?;
+        let response = callback_rx.recv().await.unwrap()?;
         let response = serde_json::from_value(response.body.unwrap_or_default())?;
         Ok(response)
     }
@@ -209,7 +209,7 @@ impl Client {
     pub fn capabilities(&self) -> &DebuggerCapabilities {
         self.capabilities
             .as_ref()
-            .expect("language server not yet initialized!")
+            .expect("debugger not yet initialized!")
     }
 
     pub async fn initialize(&mut self, adapter_id: String) -> Result<()> {
@@ -240,21 +240,19 @@ impl Client {
     }
 
     pub async fn launch(&mut self, args: serde_json::Value) -> Result<()> {
-        let mut initialized = self.listen_for_event("initialized".to_owned()).await;
+        // TODO: buffer these until initialized arrives
 
-        let res = self.request::<requests::Launch>(args);
-        let ev = initialized.recv();
-        join!(res, ev).0?;
+        let response = self.request::<requests::Launch>(args).await?;
+        log::error!("launch response {}", response);
 
         Ok(())
     }
 
     pub async fn attach(&mut self, args: serde_json::Value) -> Result<()> {
-        let mut initialized = self.listen_for_event("initialized".to_owned()).await;
+        // TODO: buffer these until initialized arrives
 
-        let res = self.request::<requests::Attach>(args);
-        let ev = initialized.recv();
-        join!(res, ev).0?;
+        let response = self.request::<requests::Attach>(args).await?;
+        log::error!("attach response {}", response);
 
         Ok(())
     }
diff --git a/helix-dap/src/transport.rs b/helix-dap/src/transport.rs
index bca1351c..062e0447 100644
--- a/helix-dap/src/transport.rs
+++ b/helix-dap/src/transport.rs
@@ -159,20 +159,17 @@ impl Transport {
     }
 
     fn process_response(res: Response) -> Result<Response> {
-        match res.success {
-            true => {
-                info!("<- DAP success in response to {}", res.request_seq);
+        if res.success {
+            info!("<- DAP success in response to {}", res.request_seq);
 
-                Ok(res)
-            }
-            false => {
-                error!(
-                    "<- DAP error {:?} ({:?}) for command #{} {}",
-                    res.message, res.body, res.request_seq, res.command
-                );
+            Ok(res)
+        } else {
+            error!(
+                "<- DAP error {:?} ({:?}) for command #{} {}",
+                res.message, res.body, res.request_seq, res.command
+            );
 
-                Err(Error::Other(anyhow::format_err!("{:?}", res.body)))
-            }
+            Err(Error::Other(anyhow::format_err!("{:?}", res.body)))
         }
     }
 
diff --git a/helix-lsp/Cargo.toml b/helix-lsp/Cargo.toml
index 409fd643..63f27cf8 100644
--- a/helix-lsp/Cargo.toml
+++ b/helix-lsp/Cargo.toml
@@ -24,4 +24,4 @@ serde = { version = "1.0", features = ["derive"] }
 serde_json = "1.0"
 thiserror = "1.0"
 tokio = { version = "1.9", features = ["rt", "rt-multi-thread", "io-util", "io-std", "time", "process", "macros", "fs", "parking_lot", "sync"] }
-tokio-stream = "0.1.7"
+tokio-stream = "0.1"
diff --git a/helix-term/Cargo.toml b/helix-term/Cargo.toml
index b42daff6..6ed60e02 100644
--- a/helix-term/Cargo.toml
+++ b/helix-term/Cargo.toml
@@ -24,6 +24,7 @@ path = "src/main.rs"
 helix-core = { version = "0.4", path = "../helix-core" }
 helix-view = { version = "0.4", path = "../helix-view" }
 helix-lsp = { version = "0.4", path = "../helix-lsp" }
+helix-dap = { version = "0.4", path = "../helix-dap" }
 
 anyhow = "1"
 once_cell = "1.8"
diff --git a/helix-term/src/application.rs b/helix-term/src/application.rs
index 3d59c33a..59072a09 100644
--- a/helix-term/src/application.rs
+++ b/helix-term/src/application.rs
@@ -245,6 +245,15 @@ impl Application {
         }
     }
 
+    pub async fn handle_debugger_message(
+        &mut self,
+        call: (),
+        server_id: usize,
+    ) {
+
+        //
+    }
+
     pub async fn handle_language_server_message(
         &mut self,
         call: helix_lsp::Call,
diff --git a/helix-term/src/commands.rs b/helix-term/src/commands.rs
index d7d50109..25367520 100644
--- a/helix-term/src/commands.rs
+++ b/helix-term/src/commands.rs
@@ -1900,6 +1900,41 @@ mod cmd {
         Ok(())
     }
 
+    fn debug(
+        cx: &mut compositor::Context,
+        _args: &[&str],
+        _event: PromptEvent,
+    ) -> anyhow::Result<()> {
+        use helix_dap::Client;
+        use helix_lsp::block_on;
+        use serde_json::to_value;
+        let (_, doc) = current!(cx.editor);
+
+        // look up config for filetype
+        // if multiple available, open picker
+
+        log::error!("1");
+
+        let client = Client::tcp_process("dlv", vec!["dap"], "-l 127.0.0.1:{}", 0);
+        let mut client = block_on(client)?;
+        log::error!("2");
+
+        let request = client.initialize("go".to_owned());
+        let _ = block_on(request)?;
+        log::error!("3");
+
+        let mut args = HashMap::new();
+        args.insert("mode", "debug");
+        // args.insert("program", "path/to/program");
+
+        let request = client.launch(to_value(args)?);
+        let _ = block_on(request)?;
+
+        log::error!("4");
+        doc.debugger = Some(client);
+        Ok(())
+    }
+
     pub const TYPABLE_COMMAND_LIST: &[TypableCommand] = &[
         TypableCommand {
             name: "quit",
@@ -2138,6 +2173,13 @@ mod cmd {
             doc: "Display tree sitter scopes, primarily for theming and development.",
             fun: tree_sitter_scopes,
             completer: None,
+        },
+        TypableCommand {
+            name: "debug",
+            alias: None,
+            doc: "Start a debug session.",
+            fun: debug,
+            completer: None,
         }
     ];
 
diff --git a/helix-view/Cargo.toml b/helix-view/Cargo.toml
index 29cfe047..b3991584 100644
--- a/helix-view/Cargo.toml
+++ b/helix-view/Cargo.toml
@@ -18,6 +18,7 @@ bitflags = "1.3"
 anyhow = "1"
 helix-core = { version = "0.4", path = "../helix-core" }
 helix-lsp = { version = "0.4", path = "../helix-lsp"}
+helix-dap = { version = "0.4", path = "../helix-dap"}
 crossterm = { version = "0.20", optional = true }
 
 # Conversion traits
@@ -25,6 +26,7 @@ once_cell = "1.8"
 url = "2"
 
 tokio = { version = "1", features = ["rt", "rt-multi-thread", "io-util", "io-std", "time", "process", "macros", "fs", "parking_lot"] }
+tokio-stream = "0.1"
 futures-util = { version = "0.3", features = ["std", "async-await"], default-features = false }
 
 slotmap = "1"
diff --git a/helix-view/src/document.rs b/helix-view/src/document.rs
index ff0c8bf4..3e8ed21c 100644
--- a/helix-view/src/document.rs
+++ b/helix-view/src/document.rs
@@ -100,6 +100,7 @@ pub struct Document {
 
     diagnostics: Vec<Diagnostic>,
     language_server: Option<Arc<helix_lsp::Client>>,
+    pub debugger: Option<helix_dap::Client>,
 }
 
 use std::fmt;
@@ -425,6 +426,7 @@ impl Document {
             history: Cell::new(History::default()),
             last_saved_revision: 0,
             language_server: None,
+            debugger: None,
             line_ending: DEFAULT_LINE_ENDING,
         }
     }
diff --git a/helix-view/src/editor.rs b/helix-view/src/editor.rs
index ec80580e..7b9f34fc 100644
--- a/helix-view/src/editor.rs
+++ b/helix-view/src/editor.rs
@@ -7,6 +7,9 @@ use crate::{
 };
 
 use futures_util::future;
+use futures_util::stream::select_all::SelectAll;
+use tokio_stream::wrappers::UnboundedReceiverStream;
+
 use std::{
     path::{Path, PathBuf},
     sync::Arc,
@@ -70,6 +73,7 @@ pub struct Editor {
     pub registers: Registers,
     pub theme: Theme,
     pub language_servers: helix_lsp::Registry,
+    pub debuggers: SelectAll<UnboundedReceiverStream<(usize, helix_dap::Payload)>>,
     pub clipboard_provider: Box<dyn ClipboardProvider>,
 
     pub syn_loader: Arc<syntax::Loader>,
@@ -107,6 +111,7 @@ impl Editor {
             selected_register: RegisterSelection::default(),
             theme: themes.default(),
             language_servers,
+            debuggers: SelectAll::new(),
             syn_loader: config_loader,
             theme_loader: themes,
             registers: Registers::default(),