Skip to content

feat(cli): add --normal flag to start TUI in outline navigation mode#54

Open
theskumar wants to merge 1 commit into
Epistates:mainfrom
theskumar:feat/normal-mode-flag
Open

feat(cli): add --normal flag to start TUI in outline navigation mode#54
theskumar wants to merge 1 commit into
Epistates:mainfrom
theskumar:feat/normal-mode-flag

Conversation

@theskumar

@theskumar theskumar commented May 20, 2026

Copy link
Copy Markdown

Problem

treemd file.md always starts in interactive element mode. Users who prefer outline navigation have to press Esc every time to switch to normal mode. There is no way to control the startup mode.

treemd README.md
# TUI opens in interactive mode (status bar: "j/k Navigate | Enter Action | Esc Exit")
# Must press Esc to reach normal outline navigation mode

Solution

Add a --normal CLI flag that starts the TUI in outline navigation mode.

treemd --normal README.md

What the flag does

  1. Guards enter_interactive_mode: the first call is blocked (one shot), keeping the TUI in AppMode::Normal. Subsequent i keypresses enter interactive mode as usual.
  2. Post-first-render cleanup: after the initial draw, any buffered input events are drained (zero-timeout poll), the outline cursor is reset to the first heading, content scroll is reset to top, and mode is forced to Normal with a redraw. This ensures a clean starting state regardless of what triggered during the first frame.

Usage with an external file picker

#!/usr/bin/env sh
f=$(fd -e md | fzf)
[ -n "$f" ] && exec treemd --normal "$f"

Testing

Two new integration tests verify the flag is accepted by the CLI parser and appears in help output.


Note: I used AI (Claude) to research the root cause and develop this fix.

@theskumar theskumar force-pushed the feat/normal-mode-flag branch from 637e601 to 17f2c76 Compare May 20, 2026 10:48
When launching treemd with a file argument from an external file picker
(e.g. fzf), buffered input events (like the Enter keypress used to
confirm selection) leak into treemd's event loop. This causes the TUI to
enter interactive element mode and scroll the outline to the last heading
instead of starting cleanly in normal/outline navigation mode.

The --normal flag:
- Forces the TUI to start in normal (outline navigation) mode
- Drains any buffered TTY input events before entering the main loop
- Blocks the first enter_interactive_mode call to prevent mode switching

This is useful for integrations where treemd is launched from tmux
keybindings, shell scripts, or other tools that pipe a file path into
treemd after an interactive selection step.
@theskumar theskumar force-pushed the feat/normal-mode-flag branch from 17f2c76 to f5e3447 Compare May 20, 2026 10:58
@nicholasjpaterno

Copy link
Copy Markdown
Contributor

Hi @theskumar — thanks for the PR and for digging into this! 🙏

I can't reproduce the behavior you're describing. treemd should already start in outline/normal navigation mode by default. The sequence:

  1. App::new() initializes mode: AppMode::Normal (src/tui/app.rs), and that's been the default for a long time — it's never been interactive-on-launch.
  2. Interactive element mode is only ever entered via the i key (EnterInteractiveMode is bound only in normal mode); nothing auto-enters it at startup, and there's no config path that sets it either.
  3. On launch the status bar shows the normal-mode string [Outline] N/N (X%) • Outline:…, not the [INTERACTIVE] / j/k Navigate | Enter Action | Esc Exit bar you quoted.

So a --normal flag would effectively be a no-op against the default behavior, which makes me think something else is going on in your setup rather than a treemd default?

Could you help me narrow it down?

  • Version/commit — what does treemd --version report, and are you building from a specific commit or branch? (If you forked a while back, your base may predate the current default.)
  • Repro — exact command you run (e.g. treemd README.md) and the full status bar text you see on the very first frame, before pressing any key.
  • Config — anything in your treemd config file? Please share it (or confirm there's none). Want to rule out a setting nudging you into interactive mode.
  • Environment — terminal/multiplexer (tmux, etc.), and whether any wrapper script or shell function is invoking treemd with extra args.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants