▍ humdrum codex / glint v1.0.2
license AGPL-3.0

feat: Ctrl+B = new note in the inbox

ff079ce7af31d76d53c1cd0fb83de9f6d34ff384
humdrum <me@humdrum.me> · 2026-06-29 08:17

parent 2a794d2d

feat: Ctrl+B = new note in the inbox

Ctrl+I can't be bound (it's Tab in terminals), so the inbox-new keybind is
Ctrl+B. Mirrors Ctrl+N (current dir): a typed picker query becomes the name,
unnamed buffers save-as into the inbox.

3 files changed

README.md +1 −0
@@ -53,6 +53,7 @@ | `Ctrl+P` | toggle the Glamour read preview |
 | `Ctrl+F` | fuzzy file picker (with live preview) |
 | `Ctrl+D` | today's daily note |
 | `Ctrl+N` | new note in the current directory (a typed picker query becomes its name) |
+| `Ctrl+B` | new note in the inbox |
 | `Ctrl+T` | cycle theme (flexoki-light → flexoki-dark → charm) |
 | `Ctrl+Q` | quit (press twice if there are unsaved changes) |
 | `Esc` | back to the editor |
internal/app/app.go +5 −1
@@ -39,6 +39,7 @@ 	discardNone pendingDiscard = iota
 	discardPicker
 	discardDaily
 	discardNew
+	discardInbox
 )
 
 // Canvas layout: a centered, percentage-width text column with a little top air.
@@ -182,7 +183,8 @@ 	}
 	// Disarm pending-discard unless the same action is being re-pressed.
 	repressed := (msg.Type == tea.KeyCtrlF && a.pending == discardPicker) ||
 		(msg.Type == tea.KeyCtrlD && a.pending == discardDaily) ||
-		(msg.Type == tea.KeyCtrlN && a.pending == discardNew)
+		(msg.Type == tea.KeyCtrlN && a.pending == discardNew) ||
+		(msg.Type == tea.KeyCtrlB && a.pending == discardInbox)
 	if !repressed {
 		a.pending = discardNone
 	}
@@ -219,6 +221,8 @@ 		a.pending = discardNone
 		return a.openDaily()
 	case tea.KeyCtrlN:
 		return a.newFile(a.currentDir(), discardNew)
+	case tea.KeyCtrlB:
+		return a.newFile(a.cfg.InboxRoot(), discardInbox)
 	case tea.KeyEsc:
 		a.mode = ModeEditor
 		return a, nil
internal/app/app_test.go +18 −0
@@ -600,3 +600,21 @@ 	if a.path != want {
 		t.Errorf("Ctrl+N note saved to %q, want %q (same dir as source)", a.path, want)
 	}
 }
+
+func TestCtrlBNewInInbox(t *testing.T) {
+	dir := t.TempDir()
+	t.Setenv("GLINT_VAULT", dir)
+	cfg := config.Default()
+	cfg.InboxDir = "Inbox"
+	a := New(cfg)
+	a.Update(tea.WindowSizeMsg{Width: 80, Height: 24})
+	a.Update(tea.KeyMsg{Type: tea.KeyCtrlB}) // new in inbox
+	a.editor.HandleKey(tea.KeyMsg{Type: tea.KeyRunes, Runes: []rune("x")})
+	a.Update(tea.KeyMsg{Type: tea.KeyCtrlS})
+	a.Update(tea.KeyMsg{Type: tea.KeyRunes, Runes: []rune("note")})
+	a.Update(tea.KeyMsg{Type: tea.KeyEnter})
+	want := filepath.Join(dir, "Inbox", "note.md")
+	if a.path != want {
+		t.Errorf("Ctrl+B note saved to %q, want %q (inbox)", a.path, want)
+	}
+}