questionary

A Python library for building pretty, interactive command-line prompts — select menus, checkboxes, autocomplete, and confirmations.

Library
PyPI
v2.1.1
2,167stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
52/100Fair
Development Activity48
Maintenance4
Community56
Maturity60
Momentum40

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
78/100Good
Architecture78
Code Quality85
Innovation65
Learning Curve85

Questionary gives Python scripts and CLI tools a clean, interactive way to ask the user for input. Instead of hand-rolling input() loops and validation logic, developers call one of eight ready-made prompt types — text, password, confirm, select, rawselect, checkbox, autocomplete, or path — each returning a Question object that renders through prompt_toolkit and yields the answer via .ask().

Multiple prompts can be chained into a Form that returns all answers as a single dict, and every prompt has an async counterpart for use inside asyncio applications. The library is used by projects like Rasa to build guided setup wizards, deployment confirmations, and other terminal-based user flows without reimplementing terminal input handling from scratch.

What You Get

  • Eight interactive prompt types out of the box: text, password, confirm, select, rawselect, checkbox, autocomplete, and path.
  • A styling system built on prompt_toolkit’s Style class for theming prompt colors, symbols, and layout per-question or globally.
  • Multi-question Form composition via questionary.form(), returning a single dict of answers instead of manual sequencing.
  • Sync and async APIs (ask/ask_async, prompt/prompt_async) so prompts drop into either a plain script or an asyncio application.
  • Full type hints and a py.typed marker for editor autocomplete and static-analysis friendliness.

Common Use Cases

  • CLI scaffolding tools (project generators) that interactively collect a name, template, and options before writing files.
  • DevOps and release scripts that confirm a destructive action (“Deploy to production?”) before proceeding.
  • Package installers and setup wizards that ask users to pick dependencies or plugins via checkbox prompts.
  • Interactive REPLs or admin CLIs that use autocomplete to suggest valid commands or file paths as the user types.

Under The Hood

Architecture Each prompt type lives in its own module under questionary/prompts/ (select.py, checkbox.py, text.py, etc.), all built around shared primitives in prompts/common.py (Choice, Separator, InquirerControl). Every prompt function constructs a prompt_toolkit Application and wraps it in a Question object (questionary/question.py), which exposes .ask(), .ask_async(), .unsafe_ask(), and .skip_if() — deferring execution until the caller invokes it, so prompts can be built, composed, or conditionally skipped before rendering. form.py layers a Form/FormField abstraction on top of Question to sequence multiple prompts and merge answers into one dict. The whole design is a thin, consistent facade over prompt_toolkit’s lower-level Application/KeyBindings machinery — if prompt_toolkit’s public API changed, every prompt module would need updating, since none of them add an internal abstraction layer between themselves and prompt_toolkit.

Tech Stack Pure Python, managed with Poetry (pyproject.toml), requiring Python >=3.10 and declaring exactly one runtime dependency: prompt_toolkit (>=2.0,<4.0). Dev tooling includes pytest with pytest-cov and Coveralls for test coverage, mypy for type checking, and a pre-commit stack of autoflake, black, isort, and flake8 for formatting/linting. Docs are built with Sphinx and hosted on Read the Docs. CI (.github/workflows/continuous-integration.yml) runs a code-quality job (lint, type-check, version validation) plus a test matrix across Ubuntu/Windows/macOS, Python 3.10–3.14, and both prompt_toolkit 2.x and 3.x.

Code Quality The tests/ directory has 19 test files, including a prompts/ subdirectory mirroring the source layout, test_form.py, test_question.py, and test_utils.py, run via pytest with coverage tracked through Coveralls. mypy type-checking and flake8 linting are enforced in CI (make types, make lint), and a pre-commit config auto-formats with black/isort before commits land. Source files carry Google-style docstrings with Args/Returns sections on nearly every public function, and the package ships a py.typed marker so downstream type checkers see full signatures.

API Design The public API favors a small, consistent surface: every prompt type is a single top-level function (questionary.select(...), questionary.checkbox(...)) returning a lazily-evaluated Question, so calling code reads declaratively and only executes on .ask(). Keyword arguments follow the same naming pattern across prompt types (qmark, style, default, use_arrow_keys), and Choice/Separator give a uniform way to build option lists across select, rawselect, and checkbox. The library doesn’t invent new interaction paradigms — it’s an ergonomic, well-documented wrapper around prompt_toolkit, itself acknowledging PyInquirer and whaaaaat as prior art — but the low-boilerplate, single-function-call ergonomics are a genuine improvement over hand-writing prompt_toolkit applications directly.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search