Index: uspace/app/nav/menu.c
===================================================================
--- uspace/app/nav/menu.c	(revision 832cbe7f6539badd99e8e5715f4a59e044c65c44)
+++ uspace/app/nav/menu.c	(revision accdf8823a3853db4616f504c82346a216b4eef0)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2023 Jiri Svoboda
+ * Copyright (c) 2025 Jiri Svoboda
  * All rights reserved.
  *
@@ -55,4 +55,5 @@
 	ui_menu_t *mfile;
 	ui_menu_entry_t *mopen;
+	ui_menu_entry_t *medit;
 	ui_menu_entry_t *mfsep;
 	ui_menu_entry_t *mexit;
@@ -82,4 +83,10 @@
 
 	ui_menu_entry_set_cb(mopen, nav_menu_file_open, (void *) menu);
+
+	rc = ui_menu_entry_create(mfile, "~E~dit", "Ctrl-E", &medit);
+	if (rc != EOK)
+		goto error;
+
+	ui_menu_entry_set_cb(medit, nav_menu_file_edit, (void *) menu);
 
 	rc = ui_menu_entry_sep_create(mfile, &mfsep);
@@ -154,4 +161,17 @@
 }
 
+/** File / Edit menu entry selected.
+ *
+ * @param mentry Menu entry
+ * @param arg Argument (navigator_t *)
+ */
+void nav_menu_file_edit(ui_menu_entry_t *mentry, void *arg)
+{
+	nav_menu_t *menu = (nav_menu_t *)arg;
+
+	if (menu->cb != NULL && menu->cb->file_edit != NULL)
+		menu->cb->file_edit(menu->cb_arg);
+}
+
 /** File / Exit menu entry selected.
  *
Index: uspace/app/nav/menu.h
===================================================================
--- uspace/app/nav/menu.h	(revision 832cbe7f6539badd99e8e5715f4a59e044c65c44)
+++ uspace/app/nav/menu.h	(revision accdf8823a3853db4616f504c82346a216b4eef0)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2021 Jiri Svoboda
+ * Copyright (c) 2025 Jiri Svoboda
  * All rights reserved.
  *
@@ -47,4 +47,5 @@
 extern ui_control_t *nav_menu_ctl(nav_menu_t *);
 extern void nav_menu_file_open(ui_menu_entry_t *, void *);
+extern void nav_menu_file_edit(ui_menu_entry_t *, void *);
 extern void nav_menu_file_exit(ui_menu_entry_t *, void *);
 
Index: uspace/app/nav/nav.c
===================================================================
--- uspace/app/nav/nav.c	(revision 832cbe7f6539badd99e8e5715f4a59e044c65c44)
+++ uspace/app/nav/nav.c	(revision accdf8823a3853db4616f504c82346a216b4eef0)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2022 Jiri Svoboda
+ * Copyright (c) 2025 Jiri Svoboda
  * All rights reserved.
  *
@@ -39,4 +39,5 @@
 #include <stdlib.h>
 #include <str.h>
+#include <task.h>
 #include <ui/fixed.h>
 #include <ui/filelist.h>
@@ -48,4 +49,6 @@
 #include "panel.h"
 
+#define EDITOR_CMD "/app/edit"
+
 static void wnd_close(ui_window_t *, void *);
 static void wnd_kbd(ui_window_t *, void *, kbd_event_t *);
@@ -57,8 +60,10 @@
 
 static void navigator_file_open(void *);
+static void navigator_file_edit(void *);
 static void navigator_file_exit(void *);
 
 static nav_menu_cb_t navigator_menu_cb = {
 	.file_open = navigator_file_open,
+	.file_edit = navigator_file_edit,
 	.file_exit = navigator_file_exit
 };
@@ -97,4 +102,7 @@
 	    (event->mods & KM_CTRL) != 0) {
 		switch (event->key) {
+		case KC_E:
+			navigator_file_edit((void *)navigator);
+			break;
 		case KC_Q:
 			ui_quit(navigator->ui);
@@ -318,4 +326,60 @@
 }
 
+/** Open file in text editor.
+ *
+ * @param panel Panel
+ * @param fname File name
+ *
+ * @return EOK on success or an error code
+ */
+static errno_t navigator_edit_file(navigator_t *navigator, const char *fname)
+{
+	task_id_t id;
+	task_wait_t wait;
+	task_exit_t texit;
+	int retval;
+	errno_t rc;
+
+	/* Free up and clean console for the child task. */
+	rc = ui_suspend(navigator->ui);
+	if (rc != EOK)
+		return rc;
+
+	rc = task_spawnl(&id, &wait, EDITOR_CMD, EDITOR_CMD, fname, NULL);
+	if (rc != EOK)
+		goto error;
+
+	rc = task_wait(&wait, &texit, &retval);
+	if ((rc != EOK) || (texit != TASK_EXIT_NORMAL))
+		goto error;
+
+	/* Resume UI operation */
+	rc = ui_resume(navigator->ui);
+	if (rc != EOK)
+		return rc;
+
+	(void) ui_paint(navigator->ui);
+	return EOK;
+error:
+	(void) ui_resume(navigator->ui);
+	(void) ui_paint(navigator->ui);
+	return rc;
+}
+
+/** File / Edit menu entry selected */
+static void navigator_file_edit(void *arg)
+{
+	navigator_t *navigator = (navigator_t *)arg;
+	ui_file_list_entry_t *entry;
+	ui_file_list_entry_attr_t attr;
+	panel_t *panel;
+
+	panel = navigator_get_active_panel(navigator);
+	entry = ui_file_list_get_cursor(panel->flist);
+	ui_file_list_entry_get_attr(entry, &attr);
+
+	(void)navigator_edit_file(navigator, attr.name);
+}
+
 /** File / Exit menu entry selected */
 static void navigator_file_exit(void *arg)
Index: uspace/app/nav/test/menu.c
===================================================================
--- uspace/app/nav/test/menu.c	(revision 832cbe7f6539badd99e8e5715f4a59e044c65c44)
+++ uspace/app/nav/test/menu.c	(revision accdf8823a3853db4616f504c82346a216b4eef0)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2021 Jiri Svoboda
+ * Copyright (c) 2025 Jiri Svoboda
  * All rights reserved.
  *
@@ -37,4 +37,5 @@
 
 static void test_menu_file_open(void *);
+static void test_menu_file_edit(void *);
 static void test_menu_file_exit(void *);
 
@@ -42,4 +43,5 @@
 static nav_menu_cb_t test_cb = {
 	.file_open = test_menu_file_open,
+	.file_edit = test_menu_file_edit,
 	.file_exit = test_menu_file_exit
 };
@@ -48,4 +50,5 @@
 typedef struct {
 	bool file_open;
+	bool file_edit;
 	bool file_exit;
 } test_resp_t;
@@ -148,4 +151,84 @@
 }
 
+/** File / Edit callback */
+PCUT_TEST(file_edit)
+{
+	ui_t *ui;
+	ui_window_t *window;
+	ui_wnd_params_t params;
+	nav_menu_t *menu;
+	test_resp_t resp;
+	errno_t rc;
+
+	rc = ui_create_disp(NULL, &ui);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+
+	ui_wnd_params_init(&params);
+	params.caption = "Test";
+
+	rc = ui_window_create(ui, &params, &window);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+
+	rc = nav_menu_create(window, &menu);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+
+	/* Call back with no callbacks set */
+	nav_menu_file_edit(NULL, menu);
+
+	/* Call back with dummy callbacks set */
+	nav_menu_set_cb(menu, &dummy_cb, &resp);
+	nav_menu_file_edit(NULL, menu);
+
+	/* Call back with test callbacks set */
+	resp.file_edit = false;
+	nav_menu_set_cb(menu, &test_cb, &resp);
+	nav_menu_file_edit(NULL, menu);
+	PCUT_ASSERT_TRUE(resp.file_edit);
+
+	nav_menu_destroy(menu);
+	ui_window_destroy(window);
+	ui_destroy(ui);
+}
+
+/** File / Exit callback */
+PCUT_TEST(file_exit)
+{
+	ui_t *ui;
+	ui_window_t *window;
+	ui_wnd_params_t params;
+	nav_menu_t *menu;
+	test_resp_t resp;
+	errno_t rc;
+
+	rc = ui_create_disp(NULL, &ui);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+
+	ui_wnd_params_init(&params);
+	params.caption = "Test";
+
+	rc = ui_window_create(ui, &params, &window);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+
+	rc = nav_menu_create(window, &menu);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+
+	/* Call back with no callbacks set */
+	nav_menu_file_exit(NULL, menu);
+
+	/* Call back with dummy callbacks set */
+	nav_menu_set_cb(menu, &dummy_cb, &resp);
+	nav_menu_file_exit(NULL, menu);
+
+	/* Call back with test callbacks set */
+	resp.file_exit = false;
+	nav_menu_set_cb(menu, &test_cb, &resp);
+	nav_menu_file_exit(NULL, menu);
+	PCUT_ASSERT_TRUE(resp.file_exit);
+
+	nav_menu_destroy(menu);
+	ui_window_destroy(window);
+	ui_destroy(ui);
+}
+
 /** Testing File / Open callback */
 static void test_menu_file_open(void *arg)
@@ -156,4 +239,12 @@
 }
 
+/** Testing File / Edit callback */
+static void test_menu_file_edit(void *arg)
+{
+	test_resp_t *resp = (test_resp_t *)arg;
+
+	resp->file_edit = true;
+}
+
 /** Testing File / Exit callback */
 static void test_menu_file_exit(void *arg)
Index: uspace/app/nav/types/menu.h
===================================================================
--- uspace/app/nav/types/menu.h	(revision 832cbe7f6539badd99e8e5715f4a59e044c65c44)
+++ uspace/app/nav/types/menu.h	(revision accdf8823a3853db4616f504c82346a216b4eef0)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2021 Jiri Svoboda
+ * Copyright (c) 2025 Jiri Svoboda
  * All rights reserved.
  *
@@ -45,4 +45,6 @@
 	/** File / Open */
 	void (*file_open)(void *);
+	/** File / Edit */
+	void (*file_edit)(void *);
 	/** File / Exit */
 	void (*file_exit)(void *);
Index: uspace/lib/ui/include/types/ui/filelist.h
===================================================================
--- uspace/lib/ui/include/types/ui/filelist.h	(revision 832cbe7f6539badd99e8e5715f4a59e044c65c44)
+++ uspace/lib/ui/include/types/ui/filelist.h	(revision accdf8823a3853db4616f504c82346a216b4eef0)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2022 Jiri Svoboda
+ * Copyright (c) 2025 Jiri Svoboda
  * All rights reserved.
  *
@@ -37,4 +37,8 @@
 #define _UI_TYPES_FILELIST_H
 
+#include <loc.h>
+#include <stdbool.h>
+#include <stdint.h>
+
 struct ui_file_list;
 typedef struct ui_file_list ui_file_list_t;
@@ -43,6 +47,15 @@
 typedef struct ui_file_list_entry ui_file_list_entry_t;
 
-struct ui_file_list_entry_attr;
-typedef struct ui_file_list_entry_attr ui_file_list_entry_attr_t;
+/** File list entry attributes */
+typedef struct ui_file_list_entry_attr {
+	/** File name */
+	const char *name;
+	/** File size */
+	uint64_t size;
+	/** @c true iff entry is a directory */
+	bool isdir;
+	/** Service number for service special entries */
+	service_id_t svc;
+} ui_file_list_entry_attr_t;
 
 /** File list callbacks */
Index: uspace/lib/ui/include/ui/filelist.h
===================================================================
--- uspace/lib/ui/include/ui/filelist.h	(revision 832cbe7f6539badd99e8e5715f4a59e044c65c44)
+++ uspace/lib/ui/include/ui/filelist.h	(revision accdf8823a3853db4616f504c82346a216b4eef0)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2023 Jiri Svoboda
+ * Copyright (c) 2025 Jiri Svoboda
  * All rights reserved.
  *
@@ -54,4 +54,6 @@
 extern errno_t ui_file_list_open(ui_file_list_t *, ui_file_list_entry_t *);
 extern ui_file_list_entry_t *ui_file_list_get_cursor(ui_file_list_t *);
+extern void ui_file_list_entry_get_attr(ui_file_list_entry_t *,
+    ui_file_list_entry_attr_t *);
 
 #endif
Index: uspace/lib/ui/private/filelist.h
===================================================================
--- uspace/lib/ui/private/filelist.h	(revision 832cbe7f6539badd99e8e5715f4a59e044c65c44)
+++ uspace/lib/ui/private/filelist.h	(revision accdf8823a3853db4616f504c82346a216b4eef0)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2023 Jiri Svoboda
+ * Copyright (c) 2025 Jiri Svoboda
  * All rights reserved.
  *
@@ -43,16 +43,4 @@
 #include <stdint.h>
 #include <types/ui/filelist.h>
-
-/** File list entry attributes */
-struct ui_file_list_entry_attr {
-	/** File name */
-	const char *name;
-	/** File size */
-	uint64_t size;
-	/** @c true iff entry is a directory */
-	bool isdir;
-	/** Service number for service special entries */
-	service_id_t svc;
-};
 
 /** File list entry */
Index: uspace/lib/ui/src/filelist.c
===================================================================
--- uspace/lib/ui/src/filelist.c	(revision 832cbe7f6539badd99e8e5715f4a59e044c65c44)
+++ uspace/lib/ui/src/filelist.c	(revision accdf8823a3853db4616f504c82346a216b4eef0)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2023 Jiri Svoboda
+ * Copyright (c) 2025 Jiri Svoboda
  * All rights reserved.
  *
@@ -535,4 +535,18 @@
 }
 
+/** Get file list entry attributes.
+ *
+ * @param entry File list entry
+ * @return Current cursor
+ */
+void ui_file_list_entry_get_attr(ui_file_list_entry_t *entry,
+    ui_file_list_entry_attr_t *attr)
+{
+	attr->name = entry->name;
+	attr->size = entry->size;
+	attr->isdir = entry->isdir;
+	attr->svc = entry->svc;
+}
+
 /** Open file list entry.
  *
