Problem
Opening external files (e.g. ~/.zshrc, config files) currently requires exiting
the TUI and running notebook ~/.zshrc from the CLI. This breaks flow — the whole
point of the TUI is staying in it.
Context
The plumbing already exists:
openFile() in cmd/file.go handles reading, editing, saving, and permission
preservation for arbitrary files
recents.RecordExternal() tracks external files in the Recent section after opening
- Input mode (
startCreate, startRename in browser.go) provides a status-bar
text prompt pattern with Enter/Esc handling and cursor blink
- External files already render in recents via
format.ShortenHome() and can be
re-opened from there
The new feature would wire these together: i → input prompt → validate path → open file.
Possible approaches
Approach A: Reuse inputMode directly
- How: Add
startImport() following the startCreate()/startRename() pattern.
Set inputPrompt = "Open file:", resolve path in inputAction callback, then
set m.selected with FilePath and quit to the browse loop.
- Pros: Minimal new code, fully consistent with existing UX
- Cons: No tab-completion for paths (can be added later)
- Files:
internal/browser/browser.go (key handler + startImport), help overlay
Approach B: Selection-based with path in Selection
- How: Same as A but instead of opening inline, return a
Selection{FilePath: path}
so the browse.go loop handles opening via existing openFile() path
- Pros: Keeps editor launch in one place (browse.go), external files return to L0
correctly via existing FromRecent logic
- Cons: None significant — this is the cleaner version of A
- Files:
internal/browser/browser.go, cmd/browse.go (already handles FilePath)
Approach B is recommended — it reuses the browse loop's existing external file handling.
Tasks
Test plan
Scope
Type: feature
Size: small
Problem
Opening external files (e.g.
~/.zshrc, config files) currently requires exitingthe TUI and running
notebook ~/.zshrcfrom the CLI. This breaks flow — the wholepoint of the TUI is staying in it.
Context
The plumbing already exists:
openFile()incmd/file.gohandles reading, editing, saving, and permissionpreservation for arbitrary files
recents.RecordExternal()tracks external files in the Recent section after openingstartCreate,startRenameinbrowser.go) provides a status-bartext prompt pattern with Enter/Esc handling and cursor blink
format.ShortenHome()and can bere-opened from there
The new feature would wire these together:
i→ input prompt → validate path → open file.Possible approaches
Approach A: Reuse inputMode directly
startImport()following thestartCreate()/startRename()pattern.Set
inputPrompt = "Open file:", resolve path ininputActioncallback, thenset
m.selectedwithFilePathand quit to the browse loop.internal/browser/browser.go(key handler + startImport), help overlayApproach B: Selection-based with path in Selection
Selection{FilePath: path}so the
browse.goloop handles opening via existingopenFile()pathcorrectly via existing
FromRecentlogicinternal/browser/browser.go,cmd/browse.go(already handles FilePath)Approach B is recommended — it reuses the browse loop's existing external file handling.
Tasks
startImport()method using the inputMode patternikey at L0 (confirm unbound — currently unused)~, resolve to absolute path, validate file existsand is readable, return
Selection{FilePath: path, FromRecent: true}i Open fileto browser help overlayTest plan
iat L0 → status bar shows "Open file:" prompt~/...) → file opens in editorScope
Type: feature
Size: small