Skip to main content

ggraft

GLSL Graft is a cli tool allowing declarative injection patches for vanilla Minecraft shaders.

Overriding a core shader means copying Mojang's file and changing one line. Do that across twenty shaders and every Minecraft update becomes twenty manual re-copies, with no record of what you actually changed. ggraft keeps the edit under version control instead of the result: you declare which line to change, and it re-derives the overrides from any version on demand.

Terminology

Concept Name
The vanilla GLSL going in base
A file declaring edits patch
Which shader it's for target
Where in the source injection point (or anchor)
One edit inside a patch injection
What it does operation: insert, replace, wrap, declare
Anchor didn't match unresolved injection
Anchor matched N times ambiguous injection
GLSL coming out patched shader

Install

From PyPI

pip install ggraft

From source

Needs Python 3.11+ and Click. Everything else is standard library.

pip install -e .

Quick start

ggraft init 26.3      # write ggraft.toml
ggraft pull           # fetch bases from misode/mcmeta
ggraft build          # apply patches -> patched shaders

Project configuration

ggraft.toml, found by walking up from the working directory. Paths resolve relative to it.

[base]
version = "26.3"                      # Minecraft version to pull
dir     = ".ggraft/base"              # where bases land (gitignore this)
source  = "assets/minecraft/shaders"  # subtree to pull, stripped from local paths
repo    = "misode/mcmeta"             # optional

[patches]
dir = "patches"

[output]
dir    = "assets/minecraft/shaders"   # required
header = true                         # stamp a provenance comment

Targets are relative to base.source: core/terrain.vsh reads from .ggraft/base/core/terrain.vsh and writes to <output.dir>/core/terrain.vsh.

Patches

name    = "iso-world"
targets = ["core/terrain.vsh", "core/rendertype_*.vsh"]
exclude = ["core/rendertype_lines.vsh"]

[[injection]]
op      = "declare"
include = "foo:iso.glsl"

[[injection]]
op   = "replace"
at   = "gl_Position = ProjMat * ModelViewMat * vec4({expr}, 1.0);"
with = "gl_Position = iso_position(ProjMat, ModelViewMat, vec4({expr}, 1.0));"

Injections apply in order, to every matching target. Patches stack in filename order.

Anchors

at is literal text, not a regex. {name} captures what sits in that position, {match} is the whole match; both are available in the replacement.

Key Meaning
at the anchor pattern
regex = true treat at as a regex, with named groups
multiline = true let one {name} (or a regex .) span lines (false by default)
occurrence = N take the Nth match (1-based)
every = true apply to all matches

No match is an unresolved injection; more than one without occurrence or every is an ambiguous injection. Both fail the build, naming the patch, injection index, target and line numbers.

Operations

Operation Keys Effect
replace with swap the anchored text
insert text, where (before/after) add text beside it
wrap prefix, suffix surround it, keeping it
declare include or text add a top-level declaration; no anchor

declare inserts after the last #include at conditional-nesting depth zero, falling back to #extension then #version, and is idempotent. Appending after the last #include in the file would strand it inside an #ifdef branch that some shader variants skip.

Commands

Command Purpose
ggraft pull [version] fetch bases; --force refetches, -j sets parallelism. Pulling another version replaces the base
ggraft build apply patches; --check dry run, -t filters by glob
ggraft targets show which patches hit which targets
ggraft init [version] write a starter config; --force overwrites

-h/--help works on the group and every command, -V/--version prints the version, and -c/--config points at a specific ggraft.toml instead of searching upwards. pull --token also reads GITHUB_TOKEN.

Build guarantees

  • --check dry run without output writes.
  • A target pattern matching no base file fails the build. What a patch orphaned by a Minecraft update looks like.
  • A patch applying to nothing fails the build, so a mistake in targets or exclude cannot disable a patch silently.
  • Stale output is pruned. Shaders ggraft wrote are recorded in .ggraft/manifest.json, and a target dropped from a patch has its override deleted on the next build. Only manifest entries are ever deleted; -t disables pruning, since a partial build cannot tell what is stale.

Bases

Uses misode/mcmeta. Tree walk might be rate limited. Set GITHUB_TOKEN or pass --token to bypass the limit.

A pull downloads into a sibling .partial directory and swaps it in, so an interrupted pull leaves the existing base untouched and a completed one leaves nothing of it behind: base.dir is replaced wholesale, never merged into.

What the directory holds — version, repo and source — is recorded in .ggraft/base.json. Pulling a different version, repo or source therefore refetches instead of reporting the base as already present, and files from the old version cannot linger as targets for the next build. A base ggraft did not record is treated as stale and refetched too. --force refetches regardless.

Tests

python -m unittest discover -s tests   # everything
python -m unittest tests.test_cli      # one module

One module per layer: test_structure, test_glsl, test_anchor, test_operations, test_engine, test_sources, test_cli. Shared shaders, project files and a network-free mcmeta client live in tests/fixtures.py.

Planned Features

  • functions injections
  • python module API

Metadata

Release files for ggraft 1.0.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for ggraft 1.0.0
File Size Uploaded Provenance Actions
ggraft-1.0.0.tar.gz 30.5 kB With provenance Details for ggraft-1.0.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for ggraft 1.0.0
File Interpreter ABI Platform Actions
ggraft-1.0.0-py3-none-any.whl Python 3 none any Details for ggraft-1.0.0-py3-none-any.whl

Total release size: 52.3 kB

Release files / ggraft-1.0.0.tar.gz

Download URL ggraft-1.0.0.tar.gz
Size 30.5 kB
Tags Source
SHA-256 checksum
How to use checksums
542b94989d79f71d43cfd507eeca65b7c8547eb50d5097ad990ec2a55da4b455
BLAKE2b-256 checksum
How to use checksums
19a8e0ba4708d3287528b2668f248fff30bb9fbd7f8ae83ddabd4ecd065a4098
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 18, 2026.

Transparency log

Release files / ggraft-1.0.0-py3-none-any.whl

Download URL ggraft-1.0.0-py3-none-any.whl
Size 21.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
019719c5e58477a0e77f81de13cd666db609cc9928203e4a9a6ef1d49157ae53
BLAKE2b-256 checksum
How to use checksums
33d709b83167545afcefca4d4d56355268e6ba57affcc27db9a61f7bc1a588d6
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 18, 2026.

Transparency log

Security for ggraft 1.0.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for ggraft-1.0.0.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 18, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page