diff --git a/helix-core/src/diagnostic.rs b/helix-core/src/diagnostic.rs
index 5056c26a..cf58b9af 100644
--- a/helix-core/src/diagnostic.rs
+++ b/helix-core/src/diagnostic.rs
@@ -1,3 +1,4 @@
+#[derive(Eq, PartialEq)]
 pub enum Severity {
     Error,
     Warning,
diff --git a/helix-term/src/commands.rs b/helix-term/src/commands.rs
index a273fc6f..eab9397c 100644
--- a/helix-term/src/commands.rs
+++ b/helix-term/src/commands.rs
@@ -42,7 +42,6 @@ pub struct Context<'a> {
     pub callback: Option<crate::compositor::Callback>,
     pub on_next_key_callback: Option<Box<dyn FnOnce(&mut Context, KeyEvent)>>,
     pub callbacks: &'a mut LspCallbacks,
-    pub status_msg: Option<String>,
 }
 
 impl<'a> Context<'a> {
@@ -97,11 +96,6 @@ impl<'a> Context<'a> {
         });
         self.callbacks.push(callback);
     }
-
-    // TODO: allow &'static str?
-    pub fn set_status(&mut self, msg: String) {
-        self.status_msg = Some(msg);
-    }
 }
 
 /// A command is a function that takes the current state and a count, and does a side-effect on the
@@ -852,6 +846,8 @@ pub fn command_mode(cx: &mut Context) {
             }
         }, // completion
         move |editor: &mut Editor, input: &str, event: PromptEvent| {
+            use helix_view::editor::Action;
+
             if event != PromptEvent::Validate {
                 return;
             }
@@ -863,16 +859,20 @@ pub fn command_mode(cx: &mut Context) {
                     editor.close(editor.view().id);
                 }
                 ["o", path] | ["open", path] => {
-                    use helix_view::editor::Action;
                     editor.open(path.into(), Action::Replace);
                 }
                 ["w"] | ["write"] => {
-                    // TODO: non-blocking via save() command
                     let id = editor.view().doc;
                     let doc = &mut editor.documents[id];
+                    if doc.path().is_none() {
+                        editor.set_error("cannot write a buffer without a filename".to_string());
+                        return;
+                    }
                     tokio::spawn(doc.save());
                 }
-
+                ["new"] => {
+                    editor.new_file(Action::Replace);
+                }
                 _ => (),
             }
         },
@@ -1585,7 +1585,7 @@ pub fn yank(cx: &mut Context) {
 
     register::set(reg, values);
 
-    cx.set_status(msg)
+    cx.editor.set_status(msg)
 }
 
 #[derive(Copy, Clone)]
diff --git a/helix-term/src/ui/editor.rs b/helix-term/src/ui/editor.rs
index 49024226..79a6ede2 100644
--- a/helix-term/src/ui/editor.rs
+++ b/helix-term/src/ui/editor.rs
@@ -28,7 +28,6 @@ use tui::{
 pub struct EditorView {
     keymap: Keymaps,
     on_next_key: Option<Box<dyn FnOnce(&mut commands::Context, KeyEvent)>>,
-    status_msg: Option<String>,
     last_insert: (commands::Command, Vec<KeyEvent>),
     completion: Option<Completion>,
 }
@@ -40,7 +39,6 @@ impl EditorView {
         Self {
             keymap: keymap::default(),
             on_next_key: None,
-            status_msg: None,
             last_insert: (commands::normal_mode, Vec::new()),
             completion: None,
         }
@@ -86,17 +84,6 @@ impl EditorView {
             1,
         );
         self.render_statusline(doc, view, area, surface, theme, is_focused);
-
-        // render status
-        if let Some(status_msg) = &self.status_msg {
-            let style = Style::default().fg(Color::Rgb(164, 160, 232)); // lavender
-            surface.set_string(
-                view.area.x,
-                view.area.y + view.area.height,
-                status_msg,
-                style,
-            );
-        }
     }
 
     pub fn render_buffer(
@@ -537,6 +524,9 @@ impl Component for EditorView {
                 EventResult::Consumed(None)
             }
             Event::Key(key) => {
+                // clear status
+                cx.editor.status_msg = None;
+
                 let (view, doc) = cx.editor.current();
                 let mode = doc.mode();
 
@@ -547,12 +537,8 @@ impl Component for EditorView {
                     callback: None,
                     callbacks: cx.callbacks,
                     on_next_key_callback: None,
-                    status_msg: None,
                 };
 
-                // clear status
-                self.status_msg = None;
-
                 if let Some(on_next_key) = self.on_next_key.take() {
                     // if there's a command waiting input, do that first
                     on_next_key(&mut cxt, key);
@@ -602,7 +588,6 @@ impl Component for EditorView {
                 }
 
                 self.on_next_key = cxt.on_next_key_callback.take();
-                self.status_msg = cxt.status_msg.take();
                 // appease borrowck
                 let callback = cxt.callback.take();
 
@@ -641,6 +626,23 @@ impl Component for EditorView {
             self.render_view(doc, view, area, surface, &cx.editor.theme, is_focused);
         }
 
+        // render status msg
+        if let Some((status_msg, severity)) = &cx.editor.status_msg {
+            use helix_view::editor::Severity;
+            let style = if *severity == Severity::Error {
+                cx.editor.theme.get("error")
+            } else {
+                Style::default().fg(Color::Rgb(164, 160, 232)) // lavender
+            };
+
+            surface.set_string(
+                area.x,
+                area.y + area.height.saturating_sub(1),
+                status_msg,
+                style,
+            );
+        }
+
         if let Some(completion) = &self.completion {
             completion.render(area, surface, cx)
             // render completion here
diff --git a/helix-view/src/editor.rs b/helix-view/src/editor.rs
index 83208f78..e9f027f3 100644
--- a/helix-view/src/editor.rs
+++ b/helix-view/src/editor.rs
@@ -7,12 +7,16 @@ use slotmap::SlotMap;
 
 use anyhow::Error;
 
+pub use helix_core::diagnostic::Severity;
+
 pub struct Editor {
     pub tree: Tree,
     pub documents: SlotMap<DocumentId, Document>,
     pub count: Option<usize>,
     pub theme: Theme,
     pub language_servers: helix_lsp::Registry,
+
+    pub status_msg: Option<(String, Severity)>,
 }
 
 #[derive(Copy, Clone)]
@@ -43,9 +47,18 @@ impl Editor {
             count: None,
             theme,
             language_servers,
+            status_msg: None,
         }
     }
 
+    pub fn set_status(&mut self, status: String) {
+        self.status_msg = Some((status, Severity::Info));
+    }
+
+    pub fn set_error(&mut self, error: String) {
+        self.status_msg = Some((error, Severity::Error));
+    }
+
     fn _refresh(&mut self) {
         for (view, _) in self.tree.views_mut() {
             let doc = &self.documents[view.doc];