FMTUTIL(1)
π FMTUTIL(1) β the group chat edition π
okay bestie, listen up β this is the fmtutil family of commands. That's three names for basically the same vibe:
fmtutilβ manage TeX formats and Metafont bases, per-userfmtutil-sysβ manage TeX formats and Metafont bases, system-widemktexfmtβ 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 r77314 (2026-01-09 17:20:28 +0100) π
So what does it do? It rebuilds and manages TeX fmts and Metafont bases β and we're collectively calling all of those "formats" here. (RIP to "mems", the old MetaPost equivalent β MetaPost doesn't use them anymore, so we don't either π.)
Here's the vibe check on how you're allowed to call it:
- If you're not in
mktexfmtmode: exactly one command must be given, filename suffixes should generally not be specified, no non-option arguments are allowed, and you can generate multiple formats at once. Slay, multitask icon β¨ - If the command name ends in
mktexfmt: only one format can be created. The only options supported are--helpand--version, and the command line must be either a format name with extension, or a plain name that gets passed as the argument to--byfmt(see below π). The full name of the generated file (if any) is written tostdout, and nothing else β no side commentary, no extra chatter, just the path, periodt. The system directories are used if they're writable, otherwise the user directories.
By default, the return status is zero if all formats requested are successfully built β otherwise it's nonzero. Simple as that π«Ά
πΈ OPTIONS πΈ
--sysβ useTEXMFSYS{VAR,CONFIG}--userβ useTEXMF{VAR,CONFIG}--cnffileFILE β read FILE instead offmtutil.cnf. You can give this multiple times, and then all the files are used π--dry-run,-nβ don't actually build anything (no formats for you today, bestie π)--fmtdirDIR β write formats under DIR instead ofTEXMF[SYS]VAR--no-engine-subdirβ don't use the 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, as long as it's in the list π§--no-strictβ exit successfully even if a format fails to build (we're being chill today)--nohashβ don't updatels-Rfiles--recorderβ pass the-recorderoption and save.flsfiles--refreshβ recreate only existing format files--status-fileFILE β 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)
π Commands (exactly one must be specified, bestie, I'm not playing) π
--allβ recreate all format files--missingβ create all missing format files--byengineENGINE β (re)create formats built with ENGINE--byfmtFORMAT β (re)create format FORMAT--byhyphenHYPHENFILE β (re)create formats that depend on HYPHENFILE--enablefmtFORMAT[/ENGINE] β enable FORMAT, as built with ENGINE--disablefmtFORMAT[/ENGINE] β disable FORMAT, as built with ENGINE. If multiple formats have the same name and different engines, the/ENGINEspecifier is required β οΈ--listcfgβ list (enabled and disabled) configurations, filtered to available formats--showhyphenFORMAT β print name of hyphen file for FORMAT--versionβ show version information and exit--helpβ show this message and exit
π ENVIRONMENT π
Okay so here's the explanation of trees and files normally used, buckle up π’
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, they're 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. Iconic merge behaviour π
So, 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, 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's 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. Gone. Poof β¨
π 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 (hold my boba π§):
- If
$TEXMFCONFIG/web2c/fmtutil.cnfor$TEXMFHOME/web2c/fmtutil.cnfappears in the list of used files, then the one listed first bykpsewhich --all(equivalently, the one returned bykpsewhich fmtutil.cnf) is used. - 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 isn't 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. Layered. Like a cute little parfait π¨
π§ 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 cap.
π 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. Don't get cute with the formatting, bestie, it's picky.
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. Just a fun lore drop π)
β 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. There it is. The whole tea β
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're not using the original TeX Live.
π₯ 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. Main character energy for your dev builds, honestly π
πΏ ENVIRONMENT πΏ (part two, the sequel)
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, everything you already know? It applies. Fr fr.
Executable location:
../../../../texk/texlive/../../../../Master/texmf-dist/scripts/texlive/fmtutil.pl
π REPORTING BUGS π
Found a bug? Tell the people, don't suffer in silence bestie π
- Report bugs to:
tex-live@tug.org - TeX Live home page:
https://tug.org/texlive/
π That's the whole page! Go forth and format, you absolute icon. π
This was TeX Live, February 2026 β mwah, take care of yourself, and remember: one command at a time ππ«Ά
π¦ 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