CLI tool
prompt-toolkit/python-prompt-toolkit avatar
prompt-toolkit/python-prompt-toolkit

prompt_toolkit: a readline replacement that expects you to wire the terminal yourself

Library for building powerful interactive command line applications in Python

10,615 stars845 forksPythonBSD-3-Clause

At a glance

What is it?
prompt_toolkit is a pure Python library for people writing interactive command line programs, with Vi registers, bracketed paste and while-you-type highlighting, but almost none of that arrives from a single function call.
Who is it for?
Choose prompt_toolkit when your Python program needs to own the terminal itself, because the feature list reaches things a plain input() call does not, and because the no global state rule lets two independent prompts live in one process. Pass on it if you only need to read one line, since the four line example is a line reader and everything above it is code you assemble.
Can I use it commercially?
Yes. BSD-3-Clause is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 25 days ago.
What is it written in?
Mainly Python, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on November 14, 2026, and from our analysis. They are not legal advice.

From daily snapshots

Star history

  • prompt-toolkit/python-prompt-toolkit10,615 ★ · +34
Star history
Repository2026-09-222026-11-14
prompt-toolkit/python-prompt-toolkit10.6k10.6k

34 Stars in the last 53 days, measured from the daily GitHub snapshot. Compare with other projects

Editorial analysis

A readline replacement that also owns the terminal

prompt_toolkit is a pure Python library for building interactive command line applications, and the project's own framing is that it could replace GNU readline while going beyond what readline does. The feature list is about terminal behaviour rather than about parsing: syntax highlighting applied to the input while you type, using a Pygments lexer, multi-line input editing, advanced code completion, reverse and forward incremental search, and selection of text for copy and paste in both Emacs and Vi style. It also claims bracketed paste support and mouse support for cursor positioning and scrolling. Two architectural claims matter more than the feature list. The library has no global state, and the philosophy section says it actively refrains from changing global state so that multiple independent instances of the same code can exist in one process. Multiple input buffers follow from the same idea. The consequence for an application author is that no setting arrives by assigning a module level global: everything belongs to the instance you construct, and two prompts in one process cannot fight over a shared configuration.

The four line prompt() example delivers none of that

Installation is a single pip line, and the starting point fits in a few lines of Python:

python
from prompt_toolkit import prompt

if __name__ == '__main__':
    answer = prompt('Give me some input: ')
    print('You said: %s' % answer)

Read that gap carefully, because it is where projects go wrong. Nothing in those lines turns on highlighting, completion, history, Vi bindings, bracketed paste or mouse reporting. What you get is a line reader that takes a prompt string and hands back a string, and every advertised behaviour has to be assembled by the caller. The project says where to go next: the examples directory, and the implementation of the prompt function itself as a good place to begin reading the source. That ordering is an instruction rather than a courtesy. If you stop at the README snippet you will conclude prompt_toolkit is a friendlier input() and design your whole command line interface around that assumption.

The dependency claim in the README and the one in pyproject.toml disagree

The feature list calls Pygments and wcwidth the only dependencies. The package metadata does not match. In pyproject.toml the runtime block is:

toml
requires-python = ">=3.10"
dependencies = ["wcwidth>=0.1.4"]

So wcwidth is the only thing pip installs for you, and its job is computing how many columns a wide character occupies, which is what keeps the cursor on the correct column when someone types Chinese text. Pygments is named as the lexer behind while-you-type syntax highlighting, but nothing pulls it in. A project that copies a highlighting example fails on import until Pygments is added by hand, and the documented install command will not surface the problem, because from the metadata's point of view the install succeeded. wcwidth also carries a floor of 0.1.4, so an environment holding an older wcwidth for an unrelated tool gets upgraded as a side effect of this dependency.

Vi bindings reach named registers and digraphs

If you select Vi key bindings, the result is not a thin readline imitation. Named registers and digraphs are listed as working Vi functionality, which means the register and digraph handling a Vi user reaches for is present rather than approximated. Text selection for copy and paste exists in Emacs style and in Vi style, so one program can offer both key families a user already has in a shell. Auto suggestions, compared in the feature list to the fish shell, sit on top of the completion machinery rather than replacing it. The price is that each of these behaviours is something you select and wire in your own code, because none of them is switched on by the prompt() call shown above.

Windows color and cursor movement fall back to Win32 APIs

Windows support exists, and the project is unusually direct about its limits. The command line window supports vt100 escape sequences on recent Windows 10 builds, and where that is unavailable the library falls back to calling Win32 APIs for color and cursor movements. Its own summary of the implementation calls this a best effort of what is possible, and says that both Unix and Windows terminals have their limitations while the Unix experience will still be a little better. Read that against the feature list: mouse support for cursor positioning and scrolling, text selection and bracketed paste are all terminal protocol behaviours, and the two protocol families are not equivalent. The consequence for a maintainer is that a cross platform tool should not promise an identical interface on both systems.

requires-python is 3.10, and the feature list never mentions async

The metadata sets requires-python to >=3.10 and the classifiers run from Python 3.10 through 3.14, with a separate classifier marking free threading as stable. The floor is therefore a real gate: anything still pinned to 3.9 in a base image or a distribution package cannot install this version, and the install command fails on that interpreter rather than degrading. Meanwhile the repository carries examples/gevent-get-input.py, examples/ssh and examples/telnet, and the development group installs asyncssh, so concurrent and remote input are exercised somewhere. The feature list itself says nothing about an async interface, so if you need one, the readthedocs documentation is where you find out whether it exists and what it is called.

Tests, type checking and linting live in dependency groups, not in the install

A plain install gives you the library and wcwidth. Everything needed to work on prompt_toolkit itself sits in dependency groups in pyproject.toml: a build group with build and setuptools, a docs group with sphinx, wcwidth, pyperclip, sphinx_copybutton and sphinx-nefertiti, and a development group with asyncssh, codecov, coverage, ipython, mypy, prek, pytest, pytest-cov, pytest-mock, ruff and typos. The source lives under src/, with tox.ini, appveyor.yml, .codecov.yml and a .pre-commit-config.yaml at the top level, and the ruff configuration targets py310. For a user this is an advantage, because the runtime surface stays at one dependency. For a contributor it means the default install is not a usable development setup, and the groups must be requested on purpose.

Release 3.0.53 landed on 2026-07-26 after an eleven month gap

Three releases are visible: 3.0.51 on 2025-04-15, 3.0.52 on 2025-08-27 and 3.0.53 on 2026-07-26, and the last push to the repository was on 2026-10-20. The version string in pyproject.toml matches the newest release, so the metadata block doubles as a pointer to current code. What the spacing shows is a slow moving, stable library rather than a fast moving one: about four months between the first two, then close to eleven months before 3.0.53. That gap is why a pin to 3.0.52 leaves out whatever changed in 3.0.53, and why reading the CHANGELOG file at the top of the repository matters more here than release notes on a package index. One inconsistency deserves a glance before you trust the status signals: the README badges target the master branch while the repository default branch is main, so the coverage badge is not describing the branch your clone is on.

Editorial conclusion

Choose prompt_toolkit when your Python program needs to own the terminal itself, because the feature list reaches things a plain input() call does not, and because the no global state rule lets two independent prompts live in one process. Pass on it if you only need to read one line, since the four line example is a line reader and everything above it is code you assemble. Before you commit, check three things: that your interpreter is 3.10 or newer, that Pygments is installed by hand because the install command will not fetch it, and that your Windows users sit on builds where the vt100 path works, or that you accept the Win32 fallback for color and cursor movement.

Frequently asked questions

What is the Python prompt?

In prompt_toolkit, prompt() is the top-level call that reads input and returns it as a string. The project's own starting example calls it the most simple example of the library and points readers at its implementation as a good place to start reading the source.

What is Python command prompt?

prompt_toolkit is a pure Python library for building interactive command line applications in Python, and the project positions it as a possible replacement for GNU readline that can be much more than that. It runs on Linux, OS X, FreeBSD, OpenBSD and Windows.

What does prompt() do?

It takes the prompt string you pass and returns what the user typed. The example passes 'Give me some input: ' to it and then prints the returned answer, so prompt() blocks for input and hands back a string.

How to open an interactive Python prompt?

ptpython is the interactive Python shell built on top of prompt_toolkit, and the README links it as the first entry in its gallery. prompt_toolkit itself is a library you import in your own program rather than a program you launch.

Official sources

  1. License: BSD-3-Clause
  2. Project website
  3. prompt-toolkit/python-prompt-toolkit on GitHub
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/prompt-toolkit-python-prompt-toolkit.svg)](https://hysenlabs.com/projects/prompt-toolkit-python-prompt-toolkit)

Star history chart for your README

markdown
[![Star history](https://hysenlabs.com/chart/prompt-toolkit-python-prompt-toolkit.svg)](https://hysenlabs.com/projects/prompt-toolkit-python-prompt-toolkit)

Was this useful?