id = "baguette"
name = "Baguette"
homepage = "https://tddworks.github.io/baguette/"
description = "Headless iOS Simulator manager and host-side input injection for iOS 26."
executables = ["baguette"]
platforms = ["macos"]
[dotfiles]
paths = [
"~/.baguette/bakeries.json",
"~/.baguette/installed.json",
]
exclude = ["~/.baguette/bakeries/", "~/.baguette/plugins/"]
secret = []
[commands]
format = 1
label = "Baguette simulator tools"
description = "Boot a headless simulator, capture screenshots and recordings, and tail its log. Input injection (tap, swipe, type), location, network and plugin commands are left out."
quality = "ai-draft"
parser = { end_of_options = "--", interleave = "permute", long_equals = true, short_attached = false, short_bundles = false }
[[commands.subcommand]]
path = ["boot"]
label = "Boot a simulator"
[[commands.subcommand.source]]
id = "ref"
kind = "help"
url = "https://github.com/tddworks/baguette/blob/main/docs/commands.md"
revision = "2026-10-27"
evidence = '''
baguette boot --udid <udid> [--no-heal]
| `--udid` | yes | | Simulator UDID |
| `--no-heal` | | | Leave the input surface alone even if Xcode 27's Device Hub has shadowed it (see `baguette heal`). |
'''
[[commands.subcommand.field]]
id = "udid"
label = "Simulator UDID"
type = "string"
option = ["--udid"]
sources = ["ref"]
[[commands.subcommand.field]]
id = "no_heal"
label = "Do not heal the input surface"
type = "boolean"
option = ["--no-heal"]
sources = ["ref"]
[[commands.subcommand.task]]
id = "boot"
label = "Boot headlessly"
fields = ["udid", "no_heal"]
required = ["udid"]
[[commands.subcommand.group]]
id = "basic"
label = "Basic"
fields = ["udid", "no_heal"]
[[commands.subcommand]]
path = ["screenshot"]
label = "Take a screenshot"
[[commands.subcommand.source]]
id = "ref"
kind = "help"
url = "https://github.com/tddworks/baguette/blob/main/docs/commands.md"
revision = "2026-10-27"
evidence = '''
baguette screenshot --udid <udid> [--output <output>] [--metadata-output <metadata-output>] [--quality <quality>] [--scale <scale>] [--size <size>] [--fit <fit>] [--background <background>] [--format <format>] [--display <display>]
| `--udid` | yes | | Simulator UDID |
| `--output` | | | Output file (defaults to stdout) |
| `--quality` | | `0.85` | JPEG quality (0.0 – 1.0); ignored for PNG |
| `--size` | | `native` | Output size: WIDTHxHEIGHT, W:H, or one of: native \| appstore-6.9 \| appstore-6.5 \| appstore-ipad-13 \| square \| 16:9 \| 9:16 \| 4:3 \| 4:5 |
| `--fit` | | `contain` | How the frame fills the size: contain, cover, stretch |
| `--background` | | `#ffffff` | Letterbox background: transparent or #RRGGBB |
| `--format` | | | Image format: png \| jpg (defaults to the --output extension, else jpg) |
| `--display` | | | Target display plane: phone \| carplay |
'''
[[commands.subcommand.field]]
id = "udid"
label = "Simulator UDID"
type = "string"
option = ["--udid"]
sources = ["ref"]
[[commands.subcommand.field]]
id = "output"
label = "Output file"
description = "Defaults to stdout."
type = "path"
option = ["--output"]
path = { kind = "file", role = "output" }
effect = "overwrite"
sources = ["ref"]
[[commands.subcommand.field]]
id = "size"
label = "Output size"
description = "WIDTHxHEIGHT, W:H, or a preset."
type = "string"
option = ["--size"]
suggestions = [{ value = "native", label = "Native" }, { value = "appstore-6.9", label = "App Store 6.9 inch" }, { value = "appstore-6.5", label = "App Store 6.5 inch" }, { value = "appstore-ipad-13", label = "App Store iPad 13 inch" }, { value = "square", label = "Square" }]
sources = ["ref"]
[[commands.subcommand.field]]
id = "fit"
label = "Fit"
type = "enum"
option = ["--fit"]
choices = [{ value = "contain", label = "Contain" }, { value = "cover", label = "Cover" }, { value = "stretch", label = "Stretch" }]
sources = ["ref"]
[[commands.subcommand.field]]
id = "format"
label = "Image format"
type = "enum"
option = ["--format"]
choices = [{ value = "png", label = "PNG" }, { value = "jpg", label = "JPEG" }]
sources = ["ref"]
[[commands.subcommand.field]]
id = "quality"
label = "JPEG quality"
description = "0.0 to 1.0; ignored for PNG."
type = "number"
option = ["--quality"]
sources = ["ref"]
[[commands.subcommand.field]]
id = "background"
label = "Letterbox background"
description = "transparent or #RRGGBB."
type = "string"
option = ["--background"]
sources = ["ref"]
[[commands.subcommand.field]]
id = "display"
label = "Display"
type = "enum"
option = ["--display"]
choices = [{ value = "phone", label = "Phone" }, { value = "carplay", label = "CarPlay" }]
sources = ["ref"]
[[commands.subcommand.task]]
id = "shot"
label = "Screenshot to a file"
fields = ["udid", "output", "size", "format"]
required = ["udid", "output"]
[[commands.subcommand.group]]
id = "basic"
label = "Basic"
fields = ["udid", "output", "size", "format"]
[[commands.subcommand.group]]
id = "advanced"
label = "Advanced"
fields = ["fit", "quality", "background", "display"]
[[commands.subcommand]]
path = ["record"]
label = "Record the screen"
[[commands.subcommand.source]]
id = "ref"
kind = "help"
url = "https://github.com/tddworks/baguette/blob/main/docs/commands.md"
revision = "2026-10-27"
evidence = '''
baguette record --udid <udid> --output <output> [--size <size>] [--fit <fit>] [--background <background>] [--fps <fps>] [--duration <duration>] [--bitrate <bitrate>]
| `--udid` | yes | | Simulator UDID |
| `--output` | yes | | Output video file — .mp4 or .mov |
| `--size` | | `native` | Output size: native \| appstore-6.9 \| appstore-6.5 \| appstore-ipad-13 \| square \| 16:9 \| 9:16 \| 4:3 \| 4:5, WIDTHxHEIGHT, or W:H |
| `--fit` | | `contain` | Frame placement: contain \| cover \| stretch |
| `--fps` | | `30` | Frames per second (1 – 120) |
| `--duration` | | | Stop N seconds after launch (omit to record until Ctrl-C) |
| `--bitrate` | | `8000000` | H.264 average bitrate (bps) |
'''
[[commands.subcommand.field]]
id = "udid"
label = "Simulator UDID"
type = "string"
option = ["--udid"]
sources = ["ref"]
[[commands.subcommand.field]]
id = "output"
label = "Output video file"
description = ".mp4 or .mov"
type = "path"
option = ["--output"]
path = { kind = "file", role = "output" }
effect = "overwrite"
sources = ["ref"]
[[commands.subcommand.field]]
id = "size"
label = "Output size"
type = "string"
option = ["--size"]
suggestions = [{ value = "native", label = "Native" }, { value = "appstore-6.9", label = "App Store 6.9 inch" }, { value = "appstore-6.5", label = "App Store 6.5 inch" }, { value = "appstore-ipad-13", label = "App Store iPad 13 inch" }, { value = "square", label = "Square" }]
sources = ["ref"]
[[commands.subcommand.field]]
id = "fit"
label = "Fit"
type = "enum"
option = ["--fit"]
choices = [{ value = "contain", label = "Contain" }, { value = "cover", label = "Cover" }, { value = "stretch", label = "Stretch" }]
sources = ["ref"]
[[commands.subcommand.field]]
id = "fps"
label = "Frames per second"
type = "integer"
option = ["--fps"]
sources = ["ref"]
[[commands.subcommand.field]]
id = "duration"
label = "Duration (seconds)"
description = "Omit to record until Ctrl-C."
type = "number"
option = ["--duration"]
sources = ["ref"]
[[commands.subcommand.field]]
id = "bitrate"
label = "Bitrate (bps)"
type = "integer"
option = ["--bitrate"]
sources = ["ref"]
[[commands.subcommand.task]]
id = "clip"
label = "Record a timed clip"
fields = ["udid", "output", "size", "duration"]
required = ["udid", "output"]
[[commands.subcommand.group]]
id = "basic"
label = "Basic"
fields = ["udid", "output", "size", "duration"]
[[commands.subcommand.group]]
id = "advanced"
label = "Advanced"
fields = ["fit", "fps", "bitrate"]
[[commands.subcommand]]
path = ["logs"]
label = "Stream the log"
[[commands.subcommand.source]]
id = "ref"
kind = "help"
url = "https://github.com/tddworks/baguette/blob/main/docs/commands.md"
revision = "2026-10-27"
evidence = '''
baguette logs --udid <udid> [--level <level>] [--style <style>] [--predicate <predicate>] [--bundle-id <bundle-id>]
| `--udid` | yes | | Simulator UDID |
| `--level` | | `info` | Minimum log level: default \| info \| debug |
| `--style` | | `default` | Output style: default \| compact \| json \| syslog \| ndjson |
| `--predicate` | | | NSPredicate string passed to `log stream --predicate` verbatim |
| `--bundle-id` | | | Convenience: filter to a specific process by bundle / image name. ANDs with --predicate when both given. |
'''
[[commands.subcommand.field]]
id = "udid"
label = "Simulator UDID"
type = "string"
option = ["--udid"]
sources = ["ref"]
[[commands.subcommand.field]]
id = "level"
label = "Minimum level"
type = "enum"
option = ["--level"]
choices = [{ value = "default", label = "Default" }, { value = "info", label = "Info" }, { value = "debug", label = "Debug" }]
sources = ["ref"]
[[commands.subcommand.field]]
id = "style"
label = "Output style"
type = "enum"
option = ["--style"]
choices = [{ value = "default", label = "Default" }, { value = "compact", label = "Compact" }, { value = "json", label = "JSON" }, { value = "syslog", label = "Syslog" }, { value = "ndjson", label = "NDJSON" }]
sources = ["ref"]
[[commands.subcommand.field]]
id = "predicate"
label = "NSPredicate filter"
type = "string"
option = ["--predicate"]
sources = ["ref"]
[[commands.subcommand.field]]
id = "bundle_id"
label = "Bundle id"
type = "string"
option = ["--bundle-id"]
sources = ["ref"]
[[commands.subcommand.task]]
id = "app_logs"
label = "Logs for one app"
fields = ["udid", "bundle_id", "level"]
required = ["udid", "bundle_id"]
[[commands.subcommand.group]]
id = "basic"
label = "Basic"
fields = ["udid", "bundle_id", "level"]
[[commands.subcommand.group]]
id = "advanced"
label = "Advanced"
fields = ["style", "predicate"]