Every generator is a plugin.
Every plugin is an MCP tool.

tt-local-generator's Generative Art tab is powered by a discoverable plugin system. Twelve built-in plugins ship with the app — SVG art, ANSI, animated GIFs, color palettes, verse, circuits, constellations, and more. Each one is also exposed as a Claude Code MCP tool, so you can call any generator directly from a conversation. Drop a new directory into ~/.config/tt-local-gen/plugins/ to add your own.

Write a plugin → Browse built-ins ↓

Plugins & transforms

All built-in plugins live in plugins/ at the repo root. Each one has an mcp.json manifest declaring its tool schema, output type, and remix graph edges, plus a plugin.py with an ArtGenerator subclass that runs the generation.

Violet SVG landscape
landscape SVG

Layered SVG landscape scenes — sky gradients, terrain silhouettes, atmospheric effects. Eleven named palettes (volcanic, arctic, toxic, midnight…). The LLM receives a structured prompt specifying horizon divisions, color zones, and decorative elements; outputs raw SVG that the app renders and archives.

Output: .svg LLM: any size Remix from: verse, palette
Metro night skyline SVG
skyline SVG

Urban skyline silhouettes against atmospheric skies. Era selector spans Victorian to brutalist to sci-fi; sky presets cover dawn through storm. Each generation produces a unique building density, bridge configuration, and light scatter pattern. Good source material for image-to-video remixing.

Output: .svg LLM: medium+ Remix from: verse
Invented constellation star chart
constellation SVG

Invented star charts with mythological lore. The LLM designs a constellation shape as a sequence of star coordinates, names the figure, and writes accompanying mythology. The SVG renderer draws the connecting lines, star glyphs at varying magnitudes, and decorative star-field scatter.

Output: .svg LLM: any size Remix from: verse
Geometric line grid SVG
geometric SVG

Abstract geometric compositions: line grids, triangle fields, hexagonal tilings, and rectangle decompositions. Three complexity levels (minimal, balanced, dense) and six named palettes. The LLM decides element placement, opacity layering, and accent color use within the palette constraints.

Output: .svg LLM: medium+ Remix from: palette
circuit SVG

PCB-style circuit diagram art. The LLM places logic gates, trace routes, pad arrays, and chip outlines in a fixed-grid SVG coordinate system. Gate shapes are selectable (ANSI, IEC, or symbolic). Output looks like a functional schematic but is purely decorative — good for backgrounds and poster art.

Output: .svg LLM: large (14B+) Remix from: palette
Drowned Ironwork  · 5 colors
palette JSON

Named color palettes with evocative prose lore. The LLM invents a 4–8 color set, names the palette ("Drowned Ironwork", "Fever Season"), and writes 2–3 sentences of sensory description — what the palette feels like, not what it looks like. Output is JSON with hex values, role labels, and lore text. Optionally exports CSS custom properties.

Output: .json LLM: any size Remix to: video, image, landscape
the last train runs empty
through stations that no longer
need to be named
verse text

Structured text art in four forms: haiku sequences (5-7-5), world-building lore fragments (codex-style, under 80 words), epitaphs (solemn, compressed), and rhyming couplets. Each form has a strict system prompt tuned for that register. Haiku shine at small model sizes; lore and epitaphs benefit from larger.

Output: .txt LLM: any size Remix to: video, image
Write anything. The LLM follows
a single instruction with no
structural constraints.
freeform text

Open-ended text generation with a single user-supplied instruction. No form constraints — the LLM writes whatever the instruction says. Useful for generating custom prompts, short prose, lists, or any text that doesn't fit a structured form. The instruction is the entire prompt; no post-processing.

Output: .txt LLM: any size Remix to: video, image
████▀▀██
█▀▀▀▀▀▀█
████████
▌▌▌▌▌▌▌▌
▐▐░▒▓▓▒░
ansi ANSI

xterm-256 color ANSI art on a 40×20 character canvas via a three-pass LLM pipeline: (1) ASCII structure — spatial composition with plain text; (2) block refinement — replace dense chars with ░▒▓█▀▄; (3) colorization — wrap each character with \033[38;5;Nm escape sequences. BBS style uses neon-on-void palette rules; scene/landscape use naturalistic colors.

Output: .ans LLM: large (8B+) Remix to: image
AnimateDiff — phosphor mountains animated GIF
animatediff GIF Blackhole

Animated GIF generation using the SD 1.4 TTNN UNet pipeline on Blackhole hardware. No server, no Docker — runs directly on the Blackhole chip via the TTNN runtime. Uses cross-frame temporal attention for motion continuity. Best subjects: natural cyclical motion — fire, water, wind, breath, foliage. ~5 min/frame on a single P300c.

Output: .gif LLM: none (diffusion) Remix to: video
ffmpeg_extract_frame
ffmpeg_convert_to_gif
ffmpeg_convert_to_mp4
ffmpeg_get_metadata
ffmpeg_resize
ffmpeg utility

Utility plugin exposing five ffmpeg operations as MCP tools. Used internally by the Remix engine for silent format conversions (e.g. video → I2V seed frame). Also callable from Claude Code sessions for media manipulation tasks. Utility plugins don't appear in the Art tab generator picker — they're infrastructure.

Type: utility (no generator) MCP tools: 5
Coming soon — MIDI generation
via tt-midi-maker MCP server.
Remix target: verse → midi
midi MCP server

Delegate plugin for the tt-midi-maker MCP server. When the server is running, generate_midi produces MIDI files from text prompts, verse, or palette hints. The manifest also declares a stream_midi tool for continuous generative MIDI output. This plugin demonstrates the MCP-server-backed pattern — no plugin.py required.

Type: MCP delegate Accepts from: verse, palette

Right-click transforms

Right-click any gallery card to apply a forge-powered transform. Results appear as new cards and feed straight into the Remix flow — use a background-removed image as a SkyReels I2V seed, or a depth map as compositing reference.

Remove background forge CPU

Isolates the foreground subject into a transparent PNG using RMBG-1.4. No hardware needed — runs in the tenstorrent Python venv in ~15–30 seconds.

Model: briaai/RMBG-1.4 Output: transparent PNG
Describe this forge CPU

Generates a natural-language caption for any image using BLIP. The caption populates the prompt field — useful as a starting point for variations or as a video prompt.

Model: Salesforce/blip-image-captioning-base Output: text caption
Show depth forge CPU

Produces a grayscale depth map from any image using GLPN-KITTI. Brighter = closer to camera. Useful as a compositing hint or ControlNet conditioning reference.

Model: vinvino02/glpn-kitti Output: grayscale PNG

AnimateDiff examples

All generated on a single Blackhole P300c, no cloud, no server.

Phosphor mountains — purple phosphor glow across distant mountains at 2am
purple phosphor glow · mountains · 2am
Kipple — scattered objects forming and dissolving
kipple · objects forming and dissolving
Cherry theremin — bioluminescent wave motion
cherry theremin · bioluminescent wave
Aleph cellar — candle flame in stone alcove
aleph cellar · candle flame cycling
Feathers bedsit — fabric rippling in wind
feathers bedsit · fabric in wind
Forking paths — water branching over stone
forking paths · water over stone

The Remix graph

Every artifact can be remixed into another type. Click 🔀 Remix on any card or in the detail panel to see valid targets. The app derives this list from each plugin's accepts_remix_from and can_remix_to declarations — no hardcoded routing tables.

Example flows

palette
video
·
image
·
landscape
·
geometric
carry: hex colors · lore prose · mood prompt
verse
video
·
image
carry: full text · theme prompt
landscape SVG
video (I2V)
·
image
carry: thumbnail · vibe phrase · source prompt
video / GIF
animate (motion ref)
·
video (I2V seed)
carry: full video OR first frame, silently extracted
image
video (SkyReels I2V)
carry: image file · prompt text

Ingredients are target-aware — the popover shows different checkboxes depending on which target you're remixing toward. Technical conversions (video → frame, SVG → PNG) happen silently via the ffmpeg plugin; you never see a dialog for them.

Write your own plugin

A plugin is a directory with two files. The app discovers it automatically. You don't need to touch the app's source code.

Directory structure

~/.config/tt-local-gen/plugins/my-plugin/
  mcp.json   # required — tool schema + app metadata
  plugin.py  # required for local generators (omit for MCP-server-backed)

Built-in plugins live in plugins/ at the repo root and ship with the app. User-installed plugins in ~/.config/tt-local-gen/plugins/ override built-ins with the same name.

How to write one

  1. 1

    Write mcp.json

    Declare the tool schema (name, description, input parameters), output type, which tab the plugin appears on, and which remix graph edges it participates in.

  2. 2

    Write plugin.py

    Extend ArtGenerator from artgen. Implement build_prompt(args) and parse_output(raw, args). Override generate_artifact(args, call_fn) for multi-pass pipelines.

  3. 3

    Test via tt-ctl

    Run tt-ctl artgen my-plugin --theme "test" --simulate to see the generated prompt without calling the LLM. Then run with a real LLM to verify output.

  4. 4

    Launch the app — it appears automatically

    The plugin loader scans both directories at startup. Your plugin appears in the Art tab generator picker, the Remix popover, and the MCP tool manifest with no additional configuration.

Minimal mcp.json

{
  "x-ttlg": {
    "output_ext": ".txt",
    "media_type": "text",
    "accepts_remix_from": ["palette", "verse"],
    "can_remix_to":       ["video", "image"],
    "tab": "generative-art",
    "hardware": null
  },
  "tools": [{
    "name": "my-generator",
    "description": "One-sentence description shown in the UI and to MCP clients",
    "inputSchema": {
      "type": "object",
      "properties": {
        "theme": { "type": "string", "default": "the void" },
        "count": { "type": "integer", "default": 1 }
      }
    },
    "examples": [{ "theme": "volcanic winter" }],
    "x-ttlg": { "streaming": null, "artifact_tool": true }
  }]
}

Minimal plugin.py

from artgen import ArtGenerator, register

@register
class MyGenerator(ArtGenerator):
    name        = "my-generator"   # must match tool name in mcp.json
    description = "One-line description"
    output_ext  = ".txt"

    def add_args(self, parser):
        parser.add_argument("--theme", default="the void")
        parser.add_argument("--count", type=int, default=1)

    def build_prompt(self, args) -> str:
        return f"Write {args.count} piece(s) about: {args.theme}"

    def parse_output(self, raw: str, args) -> str:
        import re
        cleaned = re.sub(r"<think>.*?</think>", "", raw, flags=re.DOTALL)
        return cleaned.strip()

Worked example: Vale prose-style plugin

A concrete end-to-end example: a plugin that runs the Vale prose linter on text artifacts. Demonstrates subprocess execution, LLM rewrite mode, and how the plugin chains into the remix graph as a verse → tighten → video seed pipeline.

Remix graph position
verse
freeform
→ vale-style →
video
·
image
·
verse (iterate)

Three modes: annotate (inline Vale suggestions), suggest (list of issues only), and rewrite (LLM applies the suggestions automatically). Full runnable source in docs/examples/plugins/vale-style/ — copy it to ~/.config/tt-local-gen/plugins/ to install. Narrative walkthrough in PLUGIN_AUTHORING.md.

Every plugin is an MCP tool

The built-in MCP server exposes all loaded plugins as MCP tools on port 8003. Once registered, you can call any generator — landscape, verse, animatediff, your own custom plugin — directly from a Claude Code conversation.

Setup (one-time)

# Start the MCP server
python3 app/mcp_server.py

# Print the Claude Code configuration snippet
tt-ctl mcp-config
# → {"tt-local-gen": {"url": "http://localhost:8003/mcp"}}

# Add it to Claude Code's MCP config
tt-ctl mcp-config   # outputs JSON; merge into ~/.claude/mcp.json (don't use >>)

Calling a plugin from Claude Code

After registration, all plugins appear as tt-local-gen:<tool-name>.

# Ask Claude to generate a palette and use it as a video prompt seed
> Generate a color palette for "abandoned carnival" and then use it
  to make a video prompt

# Claude calls: tt-local-gen:palette {"mood": "abandoned carnival"}
# Then remixes the palette JSON into a video prompt via the ingredient model

MCP-server-backed plugin

If your generator runs in a separate process (Node.js, a remote API, another language), declare mcp_server in mcp.json instead of writing plugin.py:

{
  "x-ttlg": {
    /* ... standard fields ... */
    "mcp_server": {
      "command": "npx",
      "args": ["-y", "my-mcp-generator"]
    }
  },
  "tools": [{ /* standard MCP tool schema */ }]
}

The app launches your server process and communicates via JSON-RPC 2.0 over stdio (standard MCP wire protocol). See plugins/midi/mcp.json for a complete example.

x-ttlg field reference

FieldTypeDescription
output_extstringFile extension for the generated artifact (.txt, .svg, .gif, .json)
media_typestringHow the app classifies this artifact (text, image, video, midi)
accepts_remix_fromstring[]Source artifact types this generator accepts as remix input
can_remix_tostring[]Target types this generator's output can be remixed into
tabstringApp tab — use generative-art for the Art tab
hardwarestring|nullblackhole, wormhole, or null (CPU)
utilitybooltrue for non-generator utility plugins (ffmpeg etc.) — hidden from Art tab picker
mcp_serverobjectPresent only for MCP-server-backed plugins: {command, args}
streaming (tool)null|"progress"|"continuous"null = one-shot; progress = SSE progress events; continuous = runs until cancelled
artifact_tool (tool)booltrue if this tool produces the primary artifact

For the full authoring guide including the complete Vale example, multi-pass pipeline patterns, and the ArtGenerator API reference, see PLUGIN_AUTHORING.md in the repository.