Automations for working with fonts: patch fonts with Nerd Fonts glyphs, normalize font name tables from filenames, adjust variable font weights, and bundle fonts into TTC/OTC collections. The tools are small, testable Python CLIs designed for predictable, scriptable workflows.
- Patching fonts with Nerd Fonts by hand requires installing FontForge and running the Font Patcher script for every file. It’s repetitive and easy to misplace outputs.
- Fonts often have noisy filenames and inconsistent internal name tables, which makes organizing and collecting them harder.
- Creating consistent weight variants or bundling families into TTC/OTC collections is tedious without clear conventions.
This repo provides focused CLIs to make those tasks reliable and repeatable, with minimal external dependencies.
Included tools
nerdify.py: Patch fonts with Nerd Fonts glyphs using Font Patcher.nameadjust.py: Normalize filename → internal name table (Family/Subfamily, Full, PostScript).weightadjust.py: Generate standard weight instances from variable TTFs (with optional offset).createcollection.py: Build a TrueType/OpenType collection (TTC/OTC) from multiple fonts.
See detailed specs under docs/spec/ organized by feature: nerdify/, name-adjust/, weight-adjust/, font-collection/.
Prerequisites
- Python 3.x and
pip. fonttools(Python) for name and collection utilities.fontforge(system binary) only fornerdify.py(Font Patcher requires it).
Steps
- Install Python dependencies:
pip install -r requirements.txt- For development:
pip install -r requirements_dev.txt
- Install FontForge (needed for
nerdify.pyonly):- Debian/Ubuntu: run
./requirements.sh(usesapt install fontforge). - macOS (Homebrew):
brew install fontforge. - Windows: install FontForge from the official distribution.
- Debian/Ubuntu: run
Optional cache/config
nerdify.pydownloadsFontPatcher.zipon first run by default. You can point to an existing patcher with--fontpatcher-dir /path/to/FontPatcherto avoid network access.
End‑to‑end example from raw fonts to a collection:
-
Normalize internal names from filenames
- Command:
python nameadjust.py ./fonts -o ./out/named - Effect: writes copies of
.ttffiles with cleaned internal names and filename stems likeFamily-Style.ttf.
- Command:
-
Patch with Nerd Fonts glyphs
- Command:
python nerdify.py ./out/named -o ./out/patched - Notes: requires
fontforge. Downloads and cachesFontPatcher.zipunless you pass--fontpatcher-dir.
- Command:
-
Generate standard weight instances (variable TTFs)
- Command:
python weightadjust.py ./out/patched -w +10 -o ./out/weights - Behavior: produces nine standard weights (Thin→Black). With
--weight-offset, shifts numeric values while clamping to the font’s supportedwghtrange.
- Command:
-
Create a TTC/OTC collection
- Command (auto type):
python createcollection.py ./out/weights -o ./out - Command (forced type/name):
python createcollection.py ./out/weights --type ttc --name MyFamily -o ./out - Output:
./out/MyFamily.ttc(or OTC for OTF inputs), with fonts ordered by OS/2 weight (ascending) and Roman before Italic.
- Command (auto type):
nerdify.py
- Description: Patch fonts with Nerd Fonts glyphs via Font Patcher.
- Usage:
python nerdify.py [PATHS ...] -o OUTDIR [--fontpatcher-dir DIR] [--cache-dir DIR] - Notes: Supports
.ttf,.otf,.ttc; traverses directories recursively; requiresfontforge.
nameadjust.py
- Description: Humanize filename → update name table (IDs 1/2/4/6).
- Usage:
python nameadjust.py [PATHS ...] [-o OUTDIR] - Notes:
.ttfonly; without-oupdates in place (renaming the file toFamily-Style.ttfif needed).
weightadjust.py
- Description: Produce standard weights from variable TTFs; optional numeric offset.
- Usage:
python weightadjust.py [PATHS ...] [-w OFFSET] [-o OUTDIR] - Notes:
.ttfonly; clamps to the font’s supportedwghtrange; rewrites internal names in outputs.- Output names:
<stem>-<WeightName>.ttf; with offset:<stem>-<WeightName>-<Resolved>.ttf. - Weights table comes from
fontweights.toml(seedocs/spec/fontweights/spec.md).
- Output names:
createcollection.py
- Description: Create TTC/OTC from
.ttfor.otfinputs. - Usage:
python createcollection.py [PATHS ...] [-o OUTDIR] [--type {ttc,otc}] [--name NAME] [--dry-run] - Notes: Infers type from inputs (all TTF → TTC, all OTF → OTC), or force with
--type. Expects inputs to have names normalized bynameadjust.py; when not unanimous, uses a minimal filename-based basename heuristic.
- Tests:
pytest -q(configured for coverage and parallel collection). - Lint:
ruff check <files>andflake8 <files>. - Format:
black <files>. - Specs: see
docs/spec/for human‑readable specs and implementation notes.
- Commands write only to the specified
-o/--outputdirectories (or in place where documented). - Network access is only used by
nerdify.pyto fetchFontPatcher.zipunless--fontpatcher-diris provided. - Filenames and internal names are sanitized conservatively for cross‑platform safety.