Skip to content

Preset operations

Presets are shorthand operations in mod.yaml. You write one line such as preset: menu-icons; the Carbon launcher expands it into one or more replace-file or replace-directory steps before patching your Roblox install at launch.

The launcher code is in project/carbon/Mods/ModPresetRegistry.cs. For working examples, copy patterns from project/builtin-mods/.

  1. Discover: On the Mods page, Carbon loads bundled mods from the app install and community folders from your profile mods/ directory (Skeleton.Mods, typically <Carbon root>/mods/<id>/).
  2. Configure: Toggles, dropdowns, and file pickers from settings render on each mod card. Changes are saved to config.json in that mod’s state directory:
    • Community mods: config.json lives next to mod.yaml inside the mod folder.
    • Built-in mods: read-only assets ship with the app; writable state (including config.json and enable/disable) lives under bin/configs/mods/<mod-id>/ (ModManager.BuiltinStateRoot).
  3. Enable: Turning a mod on removes a .disabled marker from the state directory; turning it off writes that marker. Disabled mods are skipped entirely.
  4. Apply on launch: When you start a session, ModManager.ApplyEnabledMods resolves placeholders from config.json, evaluates when / unless, expands presets, then merges or replaces files under the selected Roblox version folder. Higher priority wins when two enabled mods target the same path.

If a preset path is wrong, the patch often fails quietly in-game. Compare your folder layout with a built-in mod that uses the same preset.

After expansion Meaning
replace-file One source file overwrites one Roblox-relative target.
replace-directory with mode: merge Every file under source is copied into target, keeping other files in that folder.
replace-directory with mode: replace-tree Replace the entire target tree (rare in built-ins; defaults to merge).

Most bundle presets (sounds, menu-icons, skybox, …) expand to directory merge into a fixed Roblox root.

These names are valid in operations[].preset (case-insensitive):

Preset Expands to Default target root(s) Built-in example
cursor Four replace-file ops (same PNG to each path) Arrow cursor PNGs under content/textures/... Cursor Swapper (below)
menu-icons replace-directory merge content/textures/MenuBar Menu Bar Pack (below)
sounds replace-directory merge content/sounds movement-sounds, soft-ui-sounds
skybox Two merges: .../cubemap → PC sky textures; .../dynamic → content/sky See skybox layout below skybox-pack, night-sky
dynamic-sky replace-directory merge content/sky (none)
textures replace-directory merge content/textures (override with target) (none)
fonts Two merges content/fonts and PlatformContent/pc/fonts (none)
ui-textures replace-directory merge ExtraContent/textures/ui (override with target) Narrow with target: ExtraContent/textures/ui/InGameMenu
translations Single replace-file ExtraContent/translations/CoreScriptLocalization.csv (none)

Optional fields on any preset operation:

  • source: Required. Path under the mod folder; may use {settingKey} placeholders.
  • mode: Usually merge (default when omitted).
  • target: Only for presets that support narrowing (textures, ui-textures).
  • when / unless: Boolean setting keys; skip the operation when the condition fails.

This is the smallest preset that still shows settings → folder merge → in-game UI.

From project/builtin-mods/menubar-pack/mod.yaml:

apiVersion: carbon.mods/v1
id: menubar-pack
name: Menu Bar Pack
author: Carbon
version: 1.0.0
description: Reskin the top menu bar icons (home, chat, menu, leave, emote).
priority: 8
settings:
- key: theme
type: dropdown
label: Icon theme
description: Merges themed icons into content/textures/MenuBar.
default: neon
options: [neon, dark, minimal]
operations:
- preset: menu-icons
source: assets/menu/{theme}
mode: merge

Filenames must match what Roblox expects under content/textures/MenuBar:

menubar-pack/
mod.yaml
assets/
menu/
neon/
icon_home.png
icon_chat.png
icon_menu.png
icon_leave.png
icon_emote.png
dark/
...
minimal/
...

Carbon merges only the files you ship; it does not delete unrelated menu icons in the client.

  1. Open Mods → Installed Mods.
  2. Enable Menu Bar Pack.
  3. Expand settings and pick Icon theme (neon, dark, or minimal). The app writes theme to config.json under bin/configs/mods/menubar-pack/.
  4. Launch a game. The top menu bar should show your themed PNGs.

neon-menubar is the same preset without settings, source: assets/menu points at a single folder.

The cursor preset copies one PNG to four Roblox cursor paths (keyboard/mouse arrow + far variants). You do not list those paths yourself.

settings:
- key: useCustom
type: toggle
label: Use custom cursor
default: false
- key: cursor
type: dropdown
label: Preset cursor
default: pink
options: [pink, blue, amber, mint, high-contrast, classic]
- key: customCursor
type: file
label: Custom cursor PNG
accept: image/png
assetCategory: cursor
operations:
- preset: cursor
source: assets/cursors/{cursor}.png
unless: useCustom
- preset: cursor
source: "{customCursor}"
when: useCustom

Bundled presets are files like assets/cursors/pink.png. The Cursor sidebar section in the app is a dedicated UI for this mod; other mods use inline settings on the card.

assetCategory: cursor tells the file picker to validate PNG dimensions (see reference).

Expanded targets (from ModPresetRegistry):

  • content/textures/Cursors/KeyboardMouse/ArrowCursor.png
  • content/textures/Cursors/KeyboardMouse/ArrowFarCursor.png
  • content/textures/ArrowCursor.png
  • content/textures/ArrowFarCursor.png

The skybox preset expects two subfolders under source:

assets/sky/night/
cubemap/
sky512_bk.tex
sky512_dn.tex
sky512_ft.tex
sky512_lf.tex
sky512_rt.tex
sky512_up.tex
dynamic/
clouds.dds
sun.jpg
...
settings:
- key: preset
type: dropdown
label: Sky preset
default: night
options: [night, sunset, storm]
operations:
- preset: skybox
source: assets/sky/{preset}
mode: merge

Carbon merges cubemap/ into PlatformContent/pc/textures/sky and dynamic/ into content/sky.

Drop .mp3 / .ogg files that use Roblox’s filenames into a folder and merge into content/sounds:

operations:
- preset: sounds
source: assets/sounds
mode: merge

Example files from movement-sounds: action_jump.mp3, action_jump_land.mp3, action_footsteps_plastic.mp3.

Situation Use
One known path (oof.ogg, one PNG) type: replace-file
Several paths driven by {theme} Multiple replace-file ops (see ingame-menu-pack)
Many files in one Roblox directory preset: sounds, menu-icons, etc.
Same asset must hit multiple fixed paths preset: cursor
  1. Enable one mod at a time while testing a new preset layout.
  2. After changing settings, launch again, patches apply at launch, not live in a running client.
  3. Compare priority if two mods touch the same directory (for example two sound packs).
  4. Read launcher logs under logs/ if a mod is skipped as invalid (ModValidator warnings).