FMTUTIL(1)

πŸ“¦ version 2026.0, in alpine 3.24

πŸ’– fmtutil(1) β€” the User Commands girlies πŸ’–

okay so real talk: this is the fmtutil family of scripts, living in the User Commands section of your manual, and it's about to become your new hyperfixation. buckle up πŸŽ€

✨ NAME ✨

  • fmtutil β€” manage TeX formats and Metafont bases, per-user 🫢
  • fmtutil-sys β€” manage TeX formats and Metafont bases, system-wide πŸ‘‘
  • mktexfmt β€” create a TeX format or Metafont base 🌸

πŸ¦‹ SYNOPSIS πŸ¦‹

fmtutil [-user|-sys] [OPTION] ... [COMMAND]
fmtutil-sys [OPTION] ... [COMMAND]
fmtutil-user [OPTION] ... [COMMAND]
mktexfmt FORMAT.fmt|BASE.base|FMTNAME

πŸ’… DESCRIPTION πŸ’…

this is fmtutil version r71424 (2024-06-04 12:25:53 +0200), no cap, that's literally the version string ✨

so what does it do? it rebuilds and manages TeX fmts and Metafont bases, and everybody just collectively calls them "formats" here, that's the vibe. (MetaPost no longer uses the past-equivalent "mems", so don't come at me with that, it's giving retired πŸ’€)

here's the rules of the game, bestie:

  • if you're not operating in mktexfmt mode, exactly one command must be given β€” one, not two, not zero, we're not doing that today πŸ™ˆ
  • filename suffixes should generally not be specified
  • no non-option arguments are allowed
  • and multiple formats can be generated β€” slay, multitasking πŸ’–

if the command name ends in mktexfmt, though, only one format can be created. the only options supported are --help and --version, and the command line must be either a format name, with extension, or a plain name that is passed as the argument to --byfmt (see below, it's down there ⬇️). the full name of the generated file (if any) is written to stdout, and nothing else β€” stdout gets the filename and nothing but the filename, main character energy only. the system directories are used if they are writable, else the user directories.

by default, the return status is zero if all formats requested are successfully built, else nonzero. periodt. 🎯

🌈 OPTIONS 🌈

  • --sys β€” use TEXMFSYS{VAR,CONFIG} πŸ‘‘
  • --user β€” use TEXMF{VAR,CONFIG} 🫢
  • --cnffile FILE β€” read FILE instead of fmtutil.cnf. and yes it can be given multiple times, in which case all the files are used, we love a repeatable option ✨
  • --dry-run, -n β€” don't actually build formts. (yes "formts", that's literally how it's spelled in the source, we're keeping it, it's iconic πŸŽ€)
  • --fmtdir DIR β€” write formats under DIR instead of TEXMF[SYS]VAR
  • --no-engine-subdir β€” don't use engine-specific subdir of the fmtdir
  • --no-error-if-no-format β€” exit successfully if no format is selected
  • --no-error-if-no-engine=ENGINE1,ENGINE2,... β€” exit successfully even if a required ENGINE is missing, if it is included in the list
  • --no-strict β€” exit successfully even if a format fails to build (we're being chill about it, we're healing πŸ’œ)
  • --nohash β€” don't update ls-R files
  • --recorder β€” pass the -recorder option and save .fls files
  • --refresh β€” recreate only existing format files
  • --status-file FILE β€” append status information about built formats to FILE
  • --quiet β€” be silent 🀫
  • --catcfg β€” (does nothing, exists for compatibility)
  • --dolinks β€” (does nothing, exists for compatibility)
  • --force β€” (does nothing, exists for compatibility)
  • --test β€” (does nothing, exists for compatibility)

lowkey obsessed with the little compatibility squad at the bottom who do absolutely nothing but are still invited to the party 🫢

🎯 Commands (exactly one must be specified):

  • --all β€” recreate all format files
  • --missing β€” create all missing format files
  • --byengine ENGINE β€” (re)create formats built with ENGINE
  • --byfmt FORMAT β€” (re)create format FORMAT
  • --byhyphen HYPHENFILE β€” (re)create formats that depend on HYPHENFILE
  • --enablefmt FORMAT[/ENGINE] β€” enable FORMAT, as built with ENGINE
  • --disablefmt FORMAT[/ENGINE] β€” disable FORMAT, as built with ENGINE. if multiple formats have the same name and different engines, the /ENGINE specifier is required β€” no guessing, bestie, you gotta say which one πŸ’…
  • --listcfg β€” list (enabled and disabled) configurations, filtered to available formats
  • --showhyphen FORMAT β€” print name of hyphen file for FORMAT
  • --version β€” show version information and exit
  • --help β€” show this message and exit

🌿 ENVIRONMENT 🌿

explanation of trees and files normally used 🧚

if --cnffile is specified on the command line (possibly multiple times), its value(s) are used. otherwise, fmtutil reads all the fmtutil.cnf files found by running kpsewhich -all fmtutil.cnf, in the order returned by kpsewhich. files specified via --cnffile are first tried to be loaded directly, and if not found and the file names don't contain directory parts, are searched via kpsewhich.

in any case, if multiple fmtutil.cnf files are found, all the format definitions found in all the fmtutil.cnf files are merged. it's a whole group chat of config files, everybody gets to speak 🌈

thus, if fmtutil.cnf files are present in all trees, and the default layout is used as shipped with TeX Live, the following files are read, in the given order.

for fmtutil-sys:

TEXMFSYSCONFIG $TEXLIVE/YYYY/texmf-config/web2c/fmtutil.cnf
TEXMFSYSVAR    $TEXLIVE/YYYY/texmf-var/web2c/fmtutil.cnf
TEXMFLOCAL     $TEXLIVE/texmf-local/web2c/fmtutil.cnf
TEXMFDIST      $TEXLIVE/YYYY/texmf-dist/web2c/fmtutil.cnf

for fmtutil-user:

TEXMFCONFIG    $HOME/.texliveYYYY/texmf-config/web2c/fmtutil.cnf
TEXMFVAR       $HOME/.texliveYYYY/texmf-var/web2c/fmtutil.cnf
TEXMFHOME      $HOME/texmf/web2c/fmtutil.cnf
TEXMFSYSCONFIG $TEXLIVE/YYYY/texmf-config/web2c/fmtutil.cnf
TEXMFSYSVAR    $TEXLIVE/YYYY/texmf-var/web2c/fmtutil.cnf
TEXMFLOCAL     $TEXLIVE/texmf-local/web2c/fmtutil.cnf
TEXMFDIST      $TEXLIVE/YYYY/texmf-dist/web2c/fmtutil.cnf

(where YYYY is the TeX Live release version, okay, that's what the placeholder means, iykyk πŸŽ€)

according to the actions, fmtutil might update one of the existing cnf files or create a new fmtutil.cnf, as described below. ⬇️

where format files are written πŸ–‹οΈ

by default, format files are (re)written in $TEXMFSYSVAR/ENGINE by fmtutil-sys, and $TEXMFVAR/ENGINE by fmtutil-user, where /ENGINE is a subdirectory named for the engine used, such as "pdftex".

for mktexfmt, TEXMFSYSVAR is used if it is writable, else TEXMFVAR.

if the --fmtdir=DIR option is specified, DIR is used instead of TEXMF[SYS]VAR, but the /ENGINE subdir is still used by default.

in all cases, if the --no-engine-subdir option is specified, the /ENGINE subdir is omitted. bye subdir πŸ’¨

where configuration changes are saved πŸ’Ύ

if config files are given on the command line, then the first one given will be used to save any changes from --enable or --disable.

if the config files are taken from kpsewhich output, then the algorithm is more complicated β€” not me explaining this, but here we go:

  1. if $TEXMFCONFIG/web2c/fmtutil.cnf or $TEXMFHOME/web2c/fmtutil.cnf appears in the list of used files, then the one listed first by kpsewhich --all (equivalently, the one returned by "kpsewhich fmtutil.cnf"), is used.
  2. if neither of the above two are present and changes are made, a new config file is created in $TEXMFCONFIG/web2c/fmtutil.cnf.

in general, the idea is that if a given config file is not writable, a higher-level one can be used. that way, the distribution's settings can be overridden system-wide using TEXMFLOCAL, and system settings can be overridden again in a particular user's TEXMFHOME or TEXMFCONF. it's the circle of configs πŸ’«

resolving multiple definitions of a format πŸ₯Š

if a format is defined in more than one config file, then the definition coming from the first-listed fmtutil.cnf is used. first come, first served, no drama πŸ’…

disabling formats 🚫

fmtutil.cnf files with higher priority (listed earlier) can disable formats in lower priority (listed later) fmtutil.cnf files by writing a line like this in the higher-priority fmtutil.cnf file:

#! <fmtname> <enginename> <hyphen> <args>

the #! must be at the beginning of the line, with at least one space or tab afterward, and there must be whitespace between each word on the list. rules are rules, bestie, the parser is not flexible πŸ™ˆ

for example, you can disable the luajitlatex format by creating the file $TEXMFCONFIG/web2c/fmtutil.cnf with the line

#! luajitlatex luajittex language.dat,language.dat.lua lualatex.ini

(as it happens, the luajittex-related formats are precisely why the --no-error-if-no-engine option exists, since luajittex cannot be compiled on all platforms. so this is not needed.) cute lore drop, honestly πŸ“

fmtutil-user (fmtutil -user) vs. fmtutil-sys (fmtutil -sys) βš”οΈ

when fmtutil-sys is run or the command line option -sys is used, TEXMFSYSCONFIG and TEXMFSYSVAR are used instead of TEXMFCONFIG and TEXMFVAR, respectively. this is the primary difference between fmtutil-sys and fmtutil-user. that's it. that's the whole beef πŸ₯Š

see https://tug.org/texlive/scripts-sys-user.html for details.

other locations may be used if you give them on the command line, or these trees don't exist, or you are not using the original TeX Live. flexibility is the moment ✨

supporting development binaries πŸ§ͺ

if an engine name ends with "-dev", formats are created in the respective directory with the -dev stripped. this allows for easily running development binaries in parallel with the released binaries. parallel play but make it TeX πŸ’–


🌿 ENVIRONMENT 🌿 (round two, bestie)

this script runs TeX and Metafont to generate the fmt/base file, and thus all normal environment variables and search path rules for TeX/MF apply. so like, yes, your env vars matter here, they always did 🌸


πŸ› REPORTING BUGS πŸ›

got beef with a bug? don't suffer in silence, tell the group chat πŸ’Œ


okay that's the whole page!! this was TeX Live, dated February 2025, FMTUTIL(1), and honestly? she ate. go build yourself a format, bestie, you've earned it πŸ‘‘πŸ’–βœ¨

πŸ“¦ where this page comes from
  • alpine 3.24: texmf-dist-doc 2026.0-r0 Β· LPPL-1.0 AND LPPL-1.1 AND LPPL-1.2 AND LPPL-1.3a AND LPPL-1.3c AND GPL-2.0-only
  • πŸ’– girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms