Engine & pipeline
How it works
One palette, compiled into each app's native theme format, with tests that catch any drift.
01 / Source
One palette.json
Every color, for noir and paper, lives by role in
palette/palette.json.02 / Generation
Generated ports
make buildruns one small bash and jq script per app, writing its native theme files.03 / Validation
Tested against drift
bats suites check the palette, each port's color mapping, and that committed ports match a fresh build.
$ make build
✓ ports/noctalia✓ ports/niri✓ ports/gtk✓ ports/ghostty✓ ports/p10k✓ ports/vscode✓ ports/obsidian✓ ports/bat✓ ports/btop✓ ports/fzf✓ ports/chrome✓ ports/shiki$ make test✓ 53 tests: palette, port mappings, build freshnessQuickstart
Installation
Ports ship ready-made files, so nothing needs building. Every port page has the full steps.
From ports/ghostty, in the repo root:
mkdir -p ~/.config/ghostty/themes
cp terminal-noir-dark terminal-noir-light ~/.config/ghostty/themes/From ports/vscode, in the repo root:
scripts/install-vscode # packages a .vsix and installs it in VS Code and CursorFrom ports/bat, in the repo root:
mkdir -p "$(bat --config-dir)/themes"
cp "Terminal Noir.tmTheme" "$(bat --config-dir)/themes/"
bat cache --buildFrom ports/fzf, in the repo root:
source /path/to/terminalnoir/ports/fzf/terminal-noir.shOpen source
Contributing
Ground rules
- Colors live only in
palette/palette.json. A port never hardcodes a hex value; it reads palette roles. - Syntax colors live in
palette/syntax.jsonas palette paths (accent.primary,ansi.bright.cyan). - Generated files under
ports/are committed, so people can install a port without running anything.make testfails when they drift from the palette.
Changing a color
- Edit
palette/palette.json. - Run
make buildandmake test. - Commit the palette change together with the regenerated ports.
Adding a port
- Create
scripts/ports/<app>.shdefiningbuild_<app>, which writes its files under"$OUT/ports/<app>/". Read colors from"$PALETTE"(and"$SYNTAX"for highlighting) withjq; seescripts/ports/btop.shfor a small example. - Add
<app>to thePORTSlist inscripts/build. - Add the generated files to
GENERATEDintests/build.bats, and a mapping test intests/ports.batsthat checks the app's key slots againstpal <variant> <role>. - Write
ports/<app>/README.mdwith install steps: a# Terminal Noir for <App>title, a one-paragraph description (the site shows it on the port card), then the steps. AddREADME.pt-br.mdtoo, titled# Terminal Noir para <App>, with the same code blocks. - Register the port in
ports.json(name, category, variants, homepage) and list it in the main README. - Run
make build test lint.
Prefer the app's native theme format, and ship a light variant when the app supports switching.