Tweak Formats

A tweak is a dynamic library the loader injects into matching processes. It can be packaged either as a bundle or as a bare .dylib. Bundles are preferred: they carry resources, and their filter lives inside them.

Bundles

Installed to /Library/TweakInject/Tweaks/Bundles/.

Layout
MyTweak.bundle/
└── Contents/
    ├── Info.plist
    ├── MacOS/
    │   └── MyTweak            <- the executable
    └── Resources/
        ├── Filter.plist       <- which processes to load into
        ├── Root.plist         <- optional, a declarative settings pane
        └── icon.svg           <- optional

The loader takes the first file in Contents/MacOS as the executable, so the bundle name and the binary name do not have to match. The filter is read from Contents/Resources/Filter.plist, or from a Filter dictionary in Info.plist.

Plain dynamic libraries

Installed to /Library/TweakInject/Tweaks/DynamicLibraries/, with a .plist of the same name beside it holding the filter.

Layout
/Library/TweakInject/Tweaks/DynamicLibraries/
├── MyTweak.dylib
└── MyTweak.plist

Simpler, but there is nowhere to put resources and nowhere for a settings pane to live. Use a bundle unless you have a reason not to.

Disabled tweaks

Disabling moves a tweak rather than deleting it, to /Library/TweakInject/DisabledTweaks/, keeping the same Bundles and DynamicLibraries split. The loader does not look there, so a disabled tweak is inert without being lost.

Architecture

A tweak only loads into a process whose architecture it was built for, and is skipped quietly for any other rather than failing loudly. Building for both arm64 and arm64e covers Apple silicon; add x86_64 if you want to reach Rosetta 2 processes.