Build a Private terminfo Entry Safely

Sometimes a terminal emulator or remote host needs a small terminfo variant, and touching /usr/share/terminfo or begging for root is overkill. You will finish with a checked terminal description compiled into a private database, and proof that ncurses can actually find it through TERMINFO.

Allow about fifteen minutes. You need a shell and the ncurses tools infocmp and tic. These examples use the locally installed ncurses 6.4.20240113 from Debian package ncurses-bin 6.4+20240113-1ubuntu2.2, and everything stays under /tmp until the final per-user installation step.

1. Check the tools and the database rules

Start with ordinary, read-only checks. Nothing here needs elevated privileges:

$ command -v infocmp tic
/usr/bin/infocmp
/usr/bin/tic
$ /usr/bin/infocmp -V
ncurses 6.4.20240113
$ /usr/bin/tic -V
ncurses 6.4.20240113

A terminfo entry describes terminal capabilities: booleans, numeric values like column count, and strings holding actual control sequences. A program normally looks the name up in a compiled database, and ncurses checks TERMINFO first, then $HOME/.terminfo, then any paths in TERMINFO_DIRS, then its compiled-in system locations. An empty component in TERMINFO_DIRS stands for the system location.

Checkpoint: leave TERM alone for the first test. Whatever name you compile has to match what a program actually looks up. The examples use the standard xterm entry plus a separate local variant.

2. Export an existing entry as source

Use infocmp to read an installed entry and print terminfo source, so you are not inventing escape sequences from scratch:

$ src=$(mktemp /tmp/my-terminfo.XXXXXX)
$ /usr/bin/infocmp -1 xterm-256color > "$src"
$ sed -n '1,8p' "$src"
#       Reconstructed via infocmp from file: /usr/share/terminfo/x/xterm-256color
xterm-256color|xterm with 256 colors,
        am,
        bce,
        ccc,
        km,
        mc5i,
        mir,

-1 prints one capability per line, which makes a small edit much easier to review. The first field holds the terminal names, separated by |. Boolean capabilities stand alone; numeric ones use #; string ones use =. Fields end in commas.

Do not copy a description from a different terminal just because the name looks similar. A wrong control sequence can leave a real terminal in a genuinely confusing state. Start from the closest known entry and change only a capability you have actually tested.

3. Make one explicit, reversible change

Give the variant its own name so it can never silently replace the original. This example only touches the long description and keeps every capability from the exported entry:

$ variant=$(mktemp /tmp/my-terminfo-variant.XXXXXX)
$ sed '1s/^xterm-256color|/xterm-256color-local|/' "$src" > "$variant"
$ sed -n '1,3p' "$variant"
#       Reconstructed via infocmp from file: /usr/share/terminfo/x/xterm-256color
xterm-256color-local|xterm with 256 colors,

That variant is deliberately boring: it proves the workflow while leaving known terminal behaviour untouched. When you do need to change a capability, edit the source with a text editor, review the diff, and keep the original around. Changing clear, cursor movement, colour or keypad strings can affect every screen-oriented program that uses this entry.

Warning: do not install a source file you have not reviewed. Terminfo string capabilities are terminal control sequences, and a bad entry can send unintended bytes to a terminal or make its display unusable. Close the affected terminal, or restore the previous database path, to recover.

4. Validate the source without compiling it

Ask tic to check syntax and use references without producing any output:

$ /usr/bin/tic -c "$variant"
$ printf 'validation status: %s\n' "$?"
validation status: 0

A zero status just means the source passed the compiler's checks; it proves nothing about whether every escape sequence matches your hardware. If validation reports an unknown capability, a malformed string, or a missing use reference, stop and fix the source before compiling.

Checkpoint: the source file should contain the exact variant name you intend to request. A successful compile under a different name is not a successful lookup test.

5. Compile into a private database

Compile to a temporary directory first. tic -o picks the database location and creates the directory tree as needed:

$ db=$(mktemp -d /tmp/my-terminfo-db.XXXXXX)
$ /usr/bin/tic -o "$db" "$variant"
$ find "$db" -type f -maxdepth 3 -print
/tmp/my-terminfo-db.example/x/xterm-256color-local

The final path is normally based on the terminal name's first character. Treat the printed path as your verification, not something to type from memory. Compiling into /tmp has changed nothing in the system database.

6. Verify the private lookup

Point one command, and only one, at the private database using TERMINFO:

$ TERMINFO="$db" /usr/bin/infocmp -1 xterm-256color-local | sed -n '1,4p'
#       Reconstructed via infocmp from file: /tmp/my-terminfo-db.example/x/xterm-256color-local
xterm-256color-local|xterm with 256 colors,
        am,

This proves infocmp can find and decode the compiled entry through the exact lookup variable ncurses applications use. It does not make the entry globally available, and it does not touch another shell's environment.

To test an application, set TERMINFO for just that invocation and use the variant name as TERM:

$ TERMINFO="$db" TERM=xterm-256color-local /usr/bin/infocmp -1 | sed -n '1,3p'
#       Reconstructed via infocmp from file: /tmp/my-terminfo-db.example/x/xterm-256color-local
xterm-256color-local|xterm with 256 colors,

For a persistent personal install, compile to "$HOME/.terminfo" instead:

$ /usr/bin/tic -o "$HOME/.terminfo" "$variant"
$ TERM=xterm-256color-local /usr/bin/infocmp -1 | sed -n '1,3p'
#       Reconstructed via infocmp from file: /home/alice/.terminfo/x/xterm-256color-local
xterm-256color-local|xterm with 256 colors,

This writes under your home directory and normally needs no elevated privileges. Undo it by removing just the compiled entry, after confirming its path with infocmp -D and find "$HOME/.terminfo" -name 'xterm-*-local'. Do not remove the whole .terminfo directory: other applications may have entries living in there too.

7. Diagnose the common failures

Done means