# smenu: a selection filter for the terminal, like sed for picking lines

> smenu reads words from standard input or a file and turns them into an interactive scrolling menu, then prints the chosen entry to standard output. It is a small C program for shell scripts that need a picker without leaving the terminal.

**p-gen/smenu** — smenu started as a lightweight and flexible terminal menu generator, but quickly evolved into a powerful and versatile CLI selection tool for interactive or scripting use.

- Repository: https://github.com/p-gen/smenu
- Stars: 2,495 · Forks: 53
- Language: C
- License: MPL-2.0
- Published: 2026-09-28 · Updated: 2026-09-28 · Language: en
- Canonical page: https://hysenlabs.com/projects/p-gen-smenu

## The gap smenu fills between sed and a full TUI toolkit

Most shell scripts that need a choice either hardcode a number or pipe through a tool that takes over the whole screen. smenu sits between those. The README describes it as a selection filter, in the same sense that sed is an editing filter: text goes in on standard input, a cursor moves over it, and the selected text comes out on standard output. Nothing is drawn outside the window the program opens, and the README states that the screen is not cleared at the start or the end of execution. The selection window appears at the cursor position and the previous terminal contents are neither modified nor lost.

That last property is the reason to consider it over a full-screen picker. If your script prints context, then asks a question, the context stays visible above the menu. The intended audience is people writing shell scripts, command-line interfaces and console tools in C, shell or anything else that can spawn a process and read its stdout. The topics list on the repository includes shell-scripts, command-line-interface and tui, which matches the README's own framing.

## How the input, layout and selection actually flow

The mechanism is a filter, so the data flow is linear. smenu reads words from standard input or from a file, arranges them on the terminal in a scrolling window, and lets a cursor be moved with the keyboard or the mouse. One or more words can be selected. When the program ends, the selection is what the caller reads.

The layout is controlled from the command line. In the Linux example in the README, the options -n20, -W, -q, -c, -b, -g and -s are combined to set the number of visible lines, the word separators, and the menu behaviour. The README's own explanation of the first example says the cursor starts under VmHWM and that after moving it and pressing Enter, the shell variable R contains the chosen line. That is the whole contract: no library, no daemon, no configuration file required to get a working picker.

Internally the repository is a small set of C files, with smenu.c, list.c, index.c, utf8.c and usage.c alongside ctxopt.c for option handling and ini.c for configuration parsing. The README notes that post v0.9.15 versions use a new options system called ctxopt, that it may contain bugs, and that command line arguments may need rearranging in some cases because of it. That is a real migration cost for anyone with existing invocations.

## Installing smenu and running a first selection

The README says some Linux distributions already package smenu, and that otherwise it can be built on any system with a functional terminfo development platform. The build is driven by the provided build.sh script, which accepts the same arguments as GNU configure, and installation is a plain make install with the appropriate privileges. The README does not give a package name for any distribution, so check your own package manager first.

A build from a checkout looks like this:

```bash
./build.sh
make
make install
```

The README says to run build.sh --help to see the accepted arguments if you need to adjust the build. Once installed, the smallest useful invocation is the Unix example from the README, which feeds passwd entries into smenu and keeps the chosen line in a shell variable:

```bash
R=$(awk -F: '$3 < 100 {print $1,$3,$4,$NF}' /etc/passwd \
      | smenu -n10 -c)
echo $R
```

The -n10 option limits the window to ten lines, so on a machine with more than ten matching accounts you should see a scroll bar, which the README's sample output shows on the right edge. If you have fewer than ten matches, there is nothing to scroll and the menu is just a list. The README's Linux example uses a richer option set, including -W $':\t\n' to treat tab and newline as word separators and -s /VmH to filter as you type:

```bash
R=$(grep Vm /proc/$$/status \
      | smenu -n20 -W $':\t\n' -q -c -b -g -s /VmH)
echo $R
```

The README states the cursor should start under VmHWM in that output, and that pressing Enter after moving it leaves the chosen text in R. The -s option takes a search string, so typing narrows the list rather than moving line by line.

## Where smenu stops being the right tool

The README is unusually direct about weaknesses, and the first is right-to-left text. It lists as a known bug that right-alignment of lines written in right-to-left languages such as Farsi or Hebrew is not respected. If your menu content is in those scripts, the display will not line up the way a reader expects, and no option is documented to fix it.

UTF-8 support has its own caveats. The README says double-width characters and extended grapheme clusters are supported, but calls the grapheme cluster support experimental and says it works much better on terminals such as WezTerm or iTerm. It also requires the encoding of UTF-8 glyphs to be in canonical form, because no effort is made to normalize them. If your input comes from a source that produces decomposed sequences, you are responsible for normalizing it before it reaches smenu.

The third boundary is platform behaviour. The README warns that on systems like BSD some tests may fail, explained by differences in posix and libc implementations, notably with specific regular expressions or uncommon UTF-8 byte sequences. That does not mean smenu will not run there, but it does mean the test suite is not a clean signal on those platforms. Finally, the testing system is described as relatively young, and running ./tests.sh in the tests directory takes around 21 minutes according to the README.

## smenu against fzf and against read -p

The obvious comparison is fzf, which also reads lines from standard input and prints a selection. The difference in approach is scope. fzf is a fuzzy finder first: it ranks and filters candidate lines by a query string. smenu is a menu renderer first: it lays words out in a scrolling window with configurable separators and a cursor, and its search option is one feature among many rather than the organizing principle. The README's examples lean on layout control, such as -n for the window height and -W for the set of characters that split input into words. If your problem is picking from a list you can already see, smenu's model fits; if your problem is finding one line among thousands by typing fragments, a fuzzy finder fits better.

The other comparison is not a tool but a shell builtin. read -p gives you a prompt and a line of input, with no list, no cursor and no scrolling. smenu exists precisely because that is not enough when the choices are known ahead of time. The README's Bash example makes the difference concrete: it rebinds CTRL-R to pipe fc -lr output through sed and then smenu, replacing the default reverse search with a browsable list of recent commands, and it uses -l and -a c:7/4,b to control the layout.

## Maintenance, licence and what an upgrade costs

The repository is not archived and the last push was on 2026-04-17. The most recent release is v1.5.0 from 2025-05-26, following v1.4.0 in April 2024 and v1.3.0 in August 2023. The release cadence is roughly annual, so plan upgrades around that rather than expecting frequent point releases.

The upgrade cost is mostly in the option system. The README carries a warning for post v0.9.15 versions: they use ctxopt, the new option management system, which may contain bugs, and command line arguments may need to be rearranged in some cases because of it. The README apologizes for the extra work. If you have long smenu invocations embedded in scripts, that is the thing to re-check when you move across that boundary.

The licence is MPL-2.0, the Mozilla Public License, version 2.0, as stated in the source headers and the LICENSE file. MPL-2.0 is a file-level copyleft licence, which matters if you plan to modify smenu's own source files and distribute the result; it is not the same as a permissive licence. This is not legal advice, and the COPYRIGHT file in the repository is the place to look for the full picture.

## Conclusion

Adopt smenu if you write shell scripts or interactive CLIs that need a picker and you want the result on stdout instead of in a separate TUI library. Do not adopt it if your text is right-to-left, since the README lists right-alignment of Farsi and Hebrew as a known bug, or if you need a menu system with its own widgets and event loop. Before relying on it, run build.sh --help to see the configure-style options your platform accepts, then check the tests directory for your OS, because the README warns that some tests fail on BSD due to posix and libc differences.

## FAQ

### What is smenu?

smenu is a selection filter for the terminal, described in its README as working like sed does for editing: it reads words from standard input or a file, shows them in a scrolling window with a movable cursor, and lets you select one or more of them. The selection is then available on standard output.

### How do I install smenu on Linux?

Some Linux distributions already provide smenu as a package. Otherwise the README says to build it with the provided build.sh script, which accepts the same arguments as GNU configure, and then run make install with the appropriate privileges. The README does not name a specific distribution package.

### Does smenu clear the terminal screen when it runs?

No. The README states that the screen is not cleared at the start or the end of smenu execution, and that the selection window is displayed at the cursor position while the previous terminal contents are neither modified nor lost.

### What licence is smenu released under?

smenu is released under the Mozilla Public License, version 2.0, identified as MPL-2.0. The licence text is in the LICENSE file and the header of the source files.

### Does smenu support right-to-left languages?

The README lists one known bug in this area: right-alignment of lines written in right-to-left languages such as Farsi or Hebrew is not respected. No option is documented to work around it.

## Sources

- [Issues](https://github.com/p-gen/smenu/issues)
- [License: MPL-2.0](https://github.com/p-gen/smenu/blob/master/LICENSE)
- [p-gen/smenu on GitHub](https://github.com/p-gen/smenu)
- [README](https://github.com/p-gen/smenu/blob/master/README.md)
- [Releases](https://github.com/p-gen/smenu/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/p-gen-smenu
