TUI from Worktrees
The Python core runs fine from any git worktree — cd 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:
| Variable | Meaning |
|---|---|
NOORA_MAIN_CHECKOUT | The 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 exclusiveNOORA_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