Skip to main content

TUI from Worktrees

The Python core runs fine from any git worktreecd in and noora just works. The TypeScript surface does not: ui-tui/ needs a populated node_modules, and a fresh npm ci per worktree is slow and duplicates gigabytes across every branch you have checked out.

htui is a shell helper that closes that gap. It launches the TUI from the current worktree while borrowing node_modules from one canonical checkout — so a throwaway branch costs a symlink, not an install.

They're developer conveniences, not shipped commands. Drop them in ~/.zshrc; adapt paths to taste.

The deps-sharing model

One checkout is the deps checkout — the one place you actually run npm install. Every other worktree links against it, and only re-installs locally when its lockfile diverges (a branch that bumps a dependency must not silently run against stale packages).

Two env vars name the canonical checkout:

VariableMeaning
NOORA_MAIN_CHECKOUTThe deps checkout — where node_modules really lives, and whose .venv/bin/python runs the backend.

Neither is read by Noora itself — they're private to these helpers. The variables Noora does read are covered in Environment Variables.

htui — TUI from the worktree

The Ink TUI has a dev path already: noora --tui --dev runs the TypeScript sources via tsx instead of the prebuilt bundle. htui is a one-liner over it that also points the run at the current worktree's ui-tui/:

htui() {
local root
root="$(_noora_root)" || { echo "htui: not in a Noora checkout" >&2; return 1; }
( cd "$root" && PYTHONPATH="$root" \
"$NOORA_MAIN_CHECKOUT/.venv/bin/python" -m noora_cli.main --tui --dev "$@" )
}

--dev compiles from source, so it links ui-tui/node_modules from NOORA_MAIN_CHECKOUT when the root lockfile matches and installs locally otherwise (see _noora_root / linking helpers).

--dev and NOORA_TUI_DIR are mutually exclusive

NOORA_TUI_DIR points Noora at a prebuilt bundle (Nix, system packages), which has no source to hot-reload. If it's set in your shell, noora --tui --dev exits with an error. Run unset NOORA_TUI_DIR before htui.

Shared helpers

Both functions resolve the enclosing checkout and link deps the same way:

# The enclosing worktree, verified as a real Noora checkout.
_noora_root() {
local root
root="$(git rev-parse --show-toplevel 2>/dev/null)" || return 1
[[ -f "$root/noora_cli/main.py" && -d "$root/ui-tui" ]] && print -r "$root"
}

# Symlink node_modules from the deps checkout — never over an existing tree.
_noora_link_deps() {
local target="${1%/}" source="${2%/}"
[[ -d "$source/node_modules" ]] || return 1
[[ -e "$target/node_modules" ]] || ln -s "$source/node_modules" "$target/node_modules"
}


## See also

- [Git Worktrees](../user-guide/git-worktrees.md) — the isolation model these helpers build on
- [TUI](../user-guide/tui.md)`noora --tui --dev` and the `NOORA_TUI_DIR` prebuild path
- [Environment Variables](../reference/environment-variables.md) — every `NOORA_*` variable Noora reads