Skip to main content
Version: 0.3.3

templater

A meta-plugin: rather than targeting one app, templater renders an arbitrary set of user-supplied Go text/template files against the current tinct palette and writes each rendered output to a path you choose. Use it when there isn't (yet) a dedicated tinct output plugin for the app you want to theme — or when you want to drive several palette-derived files (CSS variables, SCSS, an i3 colour block, a custom JSON, a docs page) from a single tinct invocation.

Configuration lives in ~/.config/tinct/templater.yaml: each entry pairs a template path with an output path and a name. On every tinct generate -o templater run, the plugin loads that config, renders each enabled template against the palette using tinct's full template-function set, and writes the results.

Because the plugin doesn't know what apps it just themed, reload is entirely the user's responsibility — no signals are sent, no daemons restarted.

Installation

Via the official plugin repository

tinct plugins install templater

Build from source

cd contrib/plugins/output/templater
go build -ldflags "-X main.Version=0.0.0" -o tinct-plugin-templater
install -m 0755 tinct-plugin-templater ~/.local/bin/

Verify

which tinct-plugin-templater
tinct-plugin-templater --plugin-info | jq .

The plugin uses tinct's go-plugin RPC protocol and is discovered automatically once it's on $PATH.

Quick start

  1. Create the config:

    mkdir -p ~/.config/tinct/templates
    cp contrib/plugins/output/templater/example-config.yaml \
    ~/.config/tinct/templater.yaml
  2. Write a template (e.g. ~/.config/tinct/templates/css-vars.tmpl):

    /* Generated by tinct - {{ themeType . }} */
    :root {
    --bg: {{ get . "background" | hex }};
    --fg: {{ get . "foreground" | hex }};
    --accent: {{ get . "accent1" | hex }};
    }
  3. Wire it up in ~/.config/tinct/templater.yaml:

    templates:
    - name: css-variables
    template_path: ~/.config/tinct/templates/css-vars.tmpl
    output_path: ~/projects/myapp/src/styles/colours.css
    enabled: true
    settings:
    create_dirs: true
  4. Generate:

    tinct generate -i image -p ~/Pictures/wallpaper.jpg -o templater

Generated files

Templater itself has no fixed output set — each rendered file is defined by an entry in templater.yaml. The fixed inputs the plugin reads from are:

FilePathRole
templater.yaml (or .yml / .json)~/.config/tinct/templater.yamlThe required config: list of templates and output paths, plus global settings
User template fileswherever template_path: points (commonly ~/.config/tinct/templates/)Go text/template files rendered against the palette
User output fileswherever output_path: pointsThe rendered results — anywhere on the filesystem the user chooses

If no config is present at any of ~/.config/tinct/templater.{yaml,yml,json}, the plugin skips with a hint pointing at the README.

Bundled example templates

A few templates ship in the plugin directory as starting points. Copy and adapt:

  • templates/css-vars.tmpl — CSS custom properties.
  • templates/alacritty.yml.tmpl — Alacritty colour scheme.
  • templates/i3-colors.tmpl — i3 client.* colour block.

Integration

Templater is drop-in by design — there's no central config line to add for the plugin itself. Each individual template you write is responsible for either being a complete config file the target app loads directly, or for being included from a hand-written config (@import, source, include …) in the target app's normal way.

Two common patterns:

  • Whole-file replacement: render directly to the file your app reads (~/.config/i3/colors, then include ~/.config/i3/colors in your i3 config).
  • Sidecar palette + include: render a separate palette file, then add a single include line to the app's main config so regenerations don't disturb your hand-written settings.

Reload behaviour

Automatic

None. Templater has no knowledge of what apps the rendered files belong to, so it never sends signals or runs reload commands. (PostExecute is a deliberate no-op.)

Manual fallback

Reload each downstream app yourself, using whatever method it expects — dunstctl reload, pkill -USR1 -x foot, i3-msg reload, restart, etc. If you have multiple downstream apps, you'll probably want to wrap tinct generate ... -o templater in a shell function that reloads them all after generation.

Uninstall / revert

  1. Remove any include lines you added to downstream app configs that reference templater outputs (e.g. include ~/.config/i3/colors, @import "colours.css").

  2. Delete the generated files. There's no canonical list — refer to the output_path: entries in your ~/.config/tinct/templater.yaml. For example:

    # Inspect your config to find them:
    grep -E '^\s*output_path:' ~/.config/tinct/templater.yaml
    # Then rm each one.
  3. Reload each downstream app to drop the palette — same commands as the reload-behaviour section, run per app.

  4. Optionally remove the config and templates:

    rm ~/.config/tinct/templater.yaml
    rm -rf ~/.config/tinct/templates/ # only if these are templater-only
  5. External state: templater only writes to the paths you configure. To also remove the plugin binary:

    tinct plugins uninstall templater
    # or, for a source build:
    rm ~/.local/bin/tinct-plugin-templater

Flags

Templater accepts arguments via --plugin-args 'templater=<json>'.

ArgumentTypeDefaultDescription
configstring~/.config/tinct/templater.yamlPath to the templater config (YAML or JSON)
templates[]string(all enabled)Only render templates whose name is in this list
skip[]string(none)Skip templates whose name is in this list
verboseboolfalseVerbose render log to stderr

Example:

tinct generate -i image -p ~/wallpaper.jpg -o templater \
--plugin-args 'templater={"templates":["css-variables"],"verbose":true}'

Configuration

templater.yaml schema:

templates:
- name: <unique-name> # required, used by --templates/--skip
description: <text> # optional, free-form
template_path: <path> # required, the .tmpl file (~ expanded)
output_path: <path> # required, where the rendered file goes
enabled: <bool> # default false — set true to render

settings:
create_dirs: <bool> # default false — mkdir -p parent dirs
backup: <bool> # default false — write .backup before overwrite
backup_suffix: <string> # default ".backup"
verbose: <bool> # default false
file_mode: <octal> # default 0644

See example-config.yaml in the plugin source for a fuller worked example. QUICKSTART.md walks through the first run end-to-end.

Template data

Each template receives a ThemeData object exposing the palette via tinct's standard template helpers:

HelperUse
get . "<role>"Colour for a semantic role (e.g. background, accent1, danger)
has . "<role>"Bool — does this role exist in the current palette?
ansi . "<name>"Perceptual ANSI colour match (black, red, …, brightwhite)
hex / hexAlphaFormat a colour as #RRGGBB / #RRGGBBAA
withAlpha c fOverride alpha (0.01.0)
themeType ."dark" or "light"
.WallpaperPathSource wallpaper path, when applicable

The full reference lives at the templating docs.

Troubleshooting

Plugin skipped: "Config file not found"

ls ~/.config/tinct/templater.yaml ~/.config/tinct/templater.yml ~/.config/tinct/templater.json

At least one of those paths must exist. Copy example-config.yaml from the plugin source as a starting point.

"No templates defined in config"

Your templates: list is empty (or you've disabled every entry). Set enabled: true on at least one entry.

A template doesn't render

tinct generate -i image -p ~/wallpaper.jpg -o templater \
--plugin-args 'templater={"verbose":true}'

Verbose mode prints the config path, the number of templates, and per-template render/write results. If a template fails, it surfaces the underlying text/template parse or execute error.

Output file written but app doesn't reload

Templater never reloads downstream apps. Run the app's own reload command manually, or wrap your tinct generate call in a shell function that does it.

Output path not created

The plugin only creates parent directories if settings.create_dirs: true. Set it, or mkdir -p the parent yourself.

  • Use templater alongside any dedicated tinct output plugin — it's complementary, not a replacement. If a built-in or contrib plugin already targets your app, prefer that — you'll get reload handling, drift detection, and a tested template for free. See the output plugins index in the tinct docs site for what's available.