Minimal and ergonomic Clack-style terminal UI primitives for Python CLIs/TUIs.
uv add griphtuiGriphTUI is heavily inspired by Clack, and follows many of the same basic principles.
You'll probably want to begin with an intro:
import griphtui as gtui
gtui.intro("The grand survey")...after which you can employ a range of primitives to prompt the user:
# section header
gtui.section("Let's talk about trains")
# text input
gtui.text("What's your favorite train?")
# select
gtui.select(
"Can this train drift?",
[("Probably", "probably"), ("Definitely", "definitely")]
)
# multiselect
gtui.multiselect(
"Which of the following applies to your favorite train?",
[
("I wish it could drift", "wish", True), # toggled on by default
("I'm sad that it can't drift", "sadness", False),
("It's really nice that it can drift", "happiness", False)
]
)
# multiselect with rules
gtui.multiselect(
"Pick your stack",
[
gtui.Option("Core", "core"),
gtui.Option("Analytics", "analytics", requires={"core"}),
gtui.Option("Legacy mode", "legacy", excludes={"core"}),
]
)
# spinners
with gtui.spinner("Preparing for ethical dilemmas...") as s:
time.sleep(1)
s.update("Installing drift capabilities...")
time.sleep(1)
s.update("Updating Terms of Use...")
time.sleep(1)
s.done("Drift ready") # leaves a [+] success line on exit
# on exception, s.fail("message") leaves a [!] error line instead
# status messages
gtui.warn("Aristoteles disliked this") # info, step, success, warn or errorFinally, wrap up with an outro:
gtui.outro("That's all, folks!")There's a bit more available, eg. input validation. See the example if you want to dive deeper.
| Function | Purpose |
|---|---|
intro(title) / outro(msg) / section(title) |
frames |
note(message, title=...) |
multi-line block (e.g. a confirmation summary) |
text(label, default="") |
single-line input |
password(label, mask="·") |
masked input; mask="" hides length entirely |
confirm(label, default=True) |
y/n prompt |
select(label, options) |
single-choice picker; Option(..., disabled=True) skips navigation |
multiselect(label, options) |
multi-choice picker with optional requires / excludes rules; Option(..., disabled=True) is un-toggleable |
spinner(label) |
threaded spinner context manager; .done() / .fail() leave a final status line |
info / step / success / warn / error |
prefixed status lines |
All prompts accept an optional console= kwarg if you want to inject your own Rich Console, and an optional description= that prints a dim line under the label.
When multiselect() rules are used, referenced option values must be unique.
Linux, macOS, and Windows (uses msvcrt for raw input on Windows, termios/tty elsewhere).