Skip to content

Latest commit

 

History

History
871 lines (641 loc) · 30.9 KB

File metadata and controls

871 lines (641 loc) · 30.9 KB

Multimedia

Operations for images, audio, video and PDFs.

In CyberChef these operations preview their result in the browser (an <img>, <audio>, <video> or <iframe> element). cchef is a command-line tool, so there is no browser preview: the operations below validate the input and pass the bytes through unchanged, which you save with the global -o/--output flag or a shell redirect.

To see the result instead of saving it, two global flags present byte output — and because they are global they work for every operation that emits bytes, not just the three whose CyberChef counterparts draw a preview:

  • --preview renders an image inline, in terminals that support it: iTerm2 (and WezTerm) via the iTerm2 protocol for any format, and kitty via the kitty graphics protocol for PNG. On any other terminal, or for output that is not an image, it reports an error rather than filling the screen with bytes.
  • --data-uri writes the output as a data:<mime>;base64,… URI.
cchef generate-qr-code -i "https://example.com" --preview
cchef blur-image --in-file photo.png --amount 8 --preview
cchef render-image --in-file photo.png --data-uri

The image-transform operations (Blur, Crop, Resize, color adjustments, …) decode the image, apply the pixel operation, and re-encode to the source format (GIF is re-encoded as PNG, as CyberChef does). The operations follow the Jimp library CyberChef uses, so for lossless formats (PNG/BMP/TIFF) the pixels are identical to CyberChef — only the encoded bytes differ. Two caveats: JPEG output is re-encoded lossily and is therefore an approximation, and Rotate by angles that are not a multiple of 90° is approximate (CyberChef upscales first; cchef matches the output dimensions but not every pixel). Read raw bytes with --in-file and save with -o.

Split Colour Channels is the exception to "one input, one output": it produces three images, so it writes them into a directory given with --out-dir rather than to -o or stdout.

The four chart operations (Heatmap, Hex Density, Scatter, Series) take delimited numeric text and emit SVG on stdout — save it with -o chart.svg and open it in any browser or image viewer. The charts use d3's scales, ticks, color ramps and hexagonal binning, so the geometry matches CyberChef's. Two deliberate differences make the output valid, safe standalone SVG: the clip path is spelled clipPath (the element nodom emits, clippath, is not an SVG element, so the clip is silently ignored by real renderers), and D3's internal __data__ bindings — which carry unescaped input into attributes — are never serialized. Upstream applies that same fix, but only to Series chart.

Trailing newlines. As in CyberChef, every record must have exactly the expected number of fields — and a trailing newline makes a final empty record, so the operation fails with Each row must have length N. Most files end in a newline, so strip it when piping one in:

printf %s "$(cat points.txt)" | cchef scatter-chart -o chart.svg

Operations are listed alphabetically.

Operation Subcommand Reference
Add Text To Image add-text-to-image
Blur Image blur-image
Contain Image contain-image
Convert Image Format convert-image-format Image file formats
Cover Image cover-image
Crop Image crop-image
Dither Image dither-image
Extract EXIF extract-exif Exif
Flip Image flip-image
Generate Image generate-image
Heatmap chart heatmap-chart Heat map
Hex Density chart hex-density-chart
Image Brightness / Contrast image-brightness-contrast
Image Filter image-filter
Image Hue/Saturation/Lightness image-hue-saturation-lightness
Image Opacity image-opacity
Invert Image invert-image
Normalise Image normalise-image
Optical Character Recognition optical-character-recognition Optical character recognition
Play Media play-media
Remove EXIF remove-exif Exif
Render Image render-image Image file formats
Render PDF render-pdf PDF
Resize Image resize-image
Rotate Image rotate-image
Scatter chart scatter-chart Scatter plot
Series chart series-chart
Sharpen Image sharpen-image
Split Colour Channels split-colour-channels Channel (digital image)

The resize/crop/contain/cover operations share a resizing algorithm option — Nearest Neighbour, Bilinear (default), Bicubic, Hermite or Bezier — matching Jimp's strategies, so lossless output is pixel-identical to CyberChef.

Add Text To Image

Draws text onto an image. CyberChef renders the text with Jimp from bundled 72px Roboto bitmap-font atlases; cchef embeds those same atlases and reproduces Jimp's glyph blitting, so the result is pixel-identical for lossless formats.

Option Type Default Notes
--text string "" The text to draw. \n starts a new line.
--horizontal-align option None None uses X position; otherwise Left, Center or Right.
--vertical-align option None None uses Y position; otherwise Top, Middle or Bottom.
--x-position number 0 Left edge, when Horizontal align is None.
--y-position number 0 Top edge, when Vertical align is None.
--size number 32 Point size, minimum 8. The 72px glyphs are bicubically scaled to it.
--font-face option Roboto Roboto, Roboto Black, Roboto Mono or Roboto Slab.
--red / --green / --blue / --alpha number 255 Text color, each 0–255.

Only the four Roboto faces are available, as in CyberChef — there is no option to supply your own font. Characters outside the atlas are drawn as ?, and whitespace the atlas has no glyph for is skipped.

The text is laid out into its own bitmap before being scaled and composited, and CyberChef sizes that bitmap with Jimp's measureTextHeight. That call reserves one line per space-separated word plus one more, so text with several words gets a taller transparent block beneath it than the single drawn line needs. It only matters if you align vertically, where the extra height shifts Middle and Bottom upwards.

Simple example

cchef add-text-to-image --in-file photo.png --text "Hello" -o titled.png

Complex example

Center 40pt red Roboto Slab across the middle of the image:

cchef add-text-to-image --in-file photo.png \
  --text "CONFIDENTIAL" --font-face "Roboto Slab" --size 40 \
  --horizontal-align Center --vertical-align Middle \
  --red 255 --green 0 --blue 0 -o stamped.png

Blur Image

Blurs an image. Ported from Jimp's blur (a fast box blur) and gaussian. Pixel-identical to CyberChef for lossless formats.

Option Type Default Notes
--amount number 5 Blur radius. For Fast, an integer 1–256.
--type option Fast Fast (box blur) or Gaussian (slower, smoother).

Simple example

cchef blur-image --in-file photo.png --amount 4 --type Gaussian -o blurred.png

Contain Image

Scales an image to fit inside a Width×Height box while preserving its aspect ratio, letterboxing the remaining space. Ported from Jimp's contain.

Option Type Default Notes
--width number 100 Target box width in pixels.
--height number 100 Target box height in pixels.
--horizontal-align option Center Left, Center or Right.
--vertical-align option Middle Top, Middle or Bottom.
--resizing-algorithm option Bilinear See the note above.
--opaque-background boolean true Composite the result over opaque black instead of transparency.

Simple example

cchef contain-image --in-file photo.png --width 200 --height 200 -o boxed.png

Convert Image Format

Decodes an image and re-encodes it as JPEG, PNG, BMP or TIFF.

Option Type Default Notes
--output-format option JPEG JPEG, PNG, BMP or TIFF.
--jpeg-quality number 80 1–100. Only used for JPEG output.
--png-filter-type option Auto Accepted for compatibility; see the note below.
--png-deflate-level number 9 0–9. Only affects PNG compression, never the pixels.

For the lossless targets (PNG, BMP, TIFF) the decoded pixels are identical to CyberChef; only the encoded bytes differ, since Go and Jimp use different encoders. BMP is 24-bit, so alpha is flattened to opaque — as it is in CyberChef. JPEG output is lossy and re-encoded with Go's encoder, so it is an approximation.

PNG Filter Type and PNG Deflate Level do not change the image. Go's PNG encoder exposes no per-scanline filter selector, so the filter type is accepted and ignored, and the deflate level is mapped onto Go's four compression levels (0 → none, 1–3 → best speed, 4–7 → default, 8–9 → best compression). Decoding any of these outputs gives the same pixels regardless.

Simple example

cchef convert-image-format --in-file photo.png --output-format PNG -o photo-copy.png

Complex example

Re-encode as a high-quality JPEG:

cchef convert-image-format --in-file photo.png \
  --output-format JPEG --jpeg-quality 95 -o photo.jpg

Cover Image

Scales an image to completely fill a Width×Height box while preserving aspect ratio, cropping the overflow. Ported from Jimp's cover.

Option Type Default Notes
--width number 100 Target box width in pixels.
--height number 100 Target box height in pixels.
--horizontal-align option Center Left, Center or Right.
--vertical-align option Middle Top, Middle or Bottom.
--resizing-algorithm option Bilinear See the note above.

Simple example

cchef cover-image --in-file photo.png --width 200 --height 200 -o filled.png

Crop Image

Crops an image to a rectangular region, or automatically crops a uniform border. Ported from Jimp's crop/autocrop. An out-of-bounds region is rejected with Error cropping image. (…).

Option Type Default Notes
--x-position number 0 Left edge of the crop region.
--y-position number 0 Top edge of the crop region.
--width number 10 Region width.
--height number 10 Region height.
--autocrop boolean false Ignore the region above and trim a uniform border matching the top-left pixel.
--autocrop-tolerance number 0.02 Color-difference tolerance for the border.
--only-autocrop-frames boolean true Only crop when all four sides have a border.
--symmetric-autocrop boolean false Crop the same amount from opposite sides.
--autocrop-keep-border-px number 0 Leave this many border pixels in place.

Simple example

cchef crop-image --in-file photo.png --x-position 10 --y-position 10 --width 100 --height 80 -o cropped.png

Complex example

Trim a solid border automatically:

cchef crop-image --in-file bordered.png --autocrop -o trimmed.png

Dither Image

Applies an ordered (RGB565) dither effect. Ported from Jimp's dither. Pixel-identical to CyberChef for lossless formats. Takes no options.

Simple example

cchef dither-image --in-file photo.png -o dithered.png

Extract EXIF

Extracts EXIF metadata from an image (JPEG/TIFF). EXIF records information about the image and the device that produced it. Tag names, value formatting (rationals as decimals, EXIF dates as UNIX timestamps) and GPS coordinate conversion follow the npm exif-parser library CyberChef uses. The output lists a tag count followed by one name: value per line. Malformed input yields Could not extract EXIF data from image: ….

Takes no options. The input is raw bytes, so use the global --in-file flag or a decode step such as from-hex.

Simple example

cchef extract-exif --in-file photo.jpg

Output (from a sample with GPS metadata):

Found 9 tags.

Make: cchef
Orientation: 1
XResolution: 72
GPSLatitudeRef: N
GPSLatitude: 51.5
GPSLongitudeRef: E
GPSLongitude: 0.125
ExposureTime: 0.01
InteropIndex: 

Flip Image

Flips an image along its X (horizontal) or Y (vertical) axis. Pixel-identical to CyberChef for lossless formats.

Option Type Default Notes
--axis option Horizontal Horizontal mirrors left–right; Vertical mirrors top–bottom.

Simple example

cchef flip-image --in-file photo.png --axis Vertical -o flipped.png

Generate Image

Builds a PNG whose pixels are read straight from the input bytes — useful for eyeballing the structure of an unknown binary. Pixel-identical to CyberChef.

Option Type Default Notes
--mode option Greyscale Bytes consumed per pixel: Greyscale 1, RG 2, RGB 3, RGBA 4, Bits ⅛.
--pixel-scale-factor number 8 1–64. Each source pixel becomes an N×N block (nearest-neighbour).
--pixels-per-row number 64 1–2048. Image width, before scaling.

In Bits mode each input byte becomes eight black-or-white pixels, most significant bit first, with a set bit rendered black. Every other mode reads its channels in order and leaves alpha opaque unless the mode supplies it. The input length must be a whole number of pixels, or the operation fails with Number of bytes is not a divisor of N.

Empty input produces a single transparent row (matching Jimp's clamping) when a scale factor is set. With --pixel-scale-factor 1 there is no scaling to clamp the height, so the image would be zero pixels tall; CyberChef emits a height-0 PNG there, but Go's encoder rejects that size, so cchef reports an error instead.

Simple example

cchef generate-image --in-file firmware.bin -o firmware.png

Complex example

Render a binary one bit per pixel at 1024 bits per row, unscaled:

cchef generate-image --in-file firmware.bin \
  --mode Bits --pixels-per-row 1024 --pixel-scale-factor 1 -o bits.png

Heatmap chart

Bins two-variable data into a grid and shades each cell by how many points fall in it. Input is one x y record per line; output is SVG.

Option Type Default Notes
--record-delimiter option Line feed Line feed or CRLF.
--field-delimiter option Space Space, Comma, Semi-colon, Colon or Tab.
--number-of-vertical-bins number 25 Rows in the grid. Must be above 0.
--number-of-horizontal-bins number 25 Columns in the grid. Must be above 0.
--use-column-headers-as-labels boolean true Take the axis labels from the first record.
--x-label string "" Used when headers are not taken as labels.
--y-label string "" Used when headers are not taken as labels.
--draw-bin-edges boolean false Outline each cell.
--min-colour-value string white Color for an empty cell. Any CSS color.
--max-colour-value string black Color for the fullest cell. Any CSS color.

Cells are shaded by blending the two colors through CIELAB, as CyberChef does. The data must vary in both axes: a column of identical x or y values is rejected, since there would be nothing to spread across the bins.

Simple example

printf '100 100\n200 200\n300 300' |
  cchef heatmap-chart --number-of-vertical-bins 5 --number-of-horizontal-bins 5 -o heat.svg

Complex example

Read from a file, label the axes, outline the cells and shade white to red:

printf %s "$(cat points.csv)" |
  cchef heatmap-chart --field-delimiter Comma \
    --number-of-vertical-bins 20 --number-of-horizontal-bins 20 \
    --x-label "requests" --y-label "latency" --draw-bin-edges \
    --min-colour-value white --max-colour-value red -o heat.svg

Hex Density chart

Groups points into hexagonal cells and shades each by how many it holds — a scatter plot that stays readable when points overlap. Output is SVG.

Option Type Default Notes
--record-delimiter option Line feed Line feed or CRLF.
--field-delimiter option Space Space, Comma, Semi-colon, Colon or Tab.
--pack-radius number 25 Hexagon size used for grouping the points.
--draw-radius number 15 Hexagon size actually drawn, so cells can be spaced apart.
--use-column-headers-as-labels boolean true Take the axis labels from the first record.
--x-label string "" Used when headers are not taken as labels.
--y-label string "" Used when headers are not taken as labels.
--draw-hexagon-edges boolean false Outline each hexagon.
--min-colour-value string white Color for the emptiest hexagon. Any CSS color.
--max-colour-value string black Color for the fullest hexagon. Any CSS color.
--draw-empty-hexagons boolean false Also draw cells holding no points.

Simple example

printf '100 100\n200 200\n300 300' | cchef hex-density-chart -o hex.svg

Complex example

Tighter packing, outlined hexagons, and the empty cells filled in:

printf %s "$(cat points.csv)" |
  cchef hex-density-chart --field-delimiter Comma \
    --pack-radius 15 --draw-radius 12 --draw-hexagon-edges \
    --draw-empty-hexagons \
    --min-colour-value white --max-colour-value blue -o hex.svg

Image Brightness / Contrast

Adjusts image brightness and/or contrast. Ported from Jimp's brightness/contrast. Pixel-identical to CyberChef for lossless formats.

Option Type Default Notes
--brightness number 0 −100 to 100. 0 leaves brightness unchanged.
--contrast number 0 −100 to 100. 0 leaves contrast unchanged.

Simple example

cchef image-brightness-contrast --in-file photo.png --brightness 20 --contrast 15 -o adjusted.png

Image Filter

Applies a grayscale or sepia filter to an image (Jimp's greyscale/sepia). Pixel-identical to CyberChef for lossless formats.

Option Type Default Notes
--filter-type option Greyscale Greyscale (Rec. 709 luminance) or Sepia.

Simple example

cchef image-filter --in-file photo.png --filter-type Sepia -o sepia.png

Image Hue/Saturation/Lightness

Adjusts an image's hue, saturation and lightness in HSL space. Ported from CyberChef's operation (Jimp's color() via tinycolor), pixel-identical to CyberChef for lossless formats.

Option Type Default Notes
--hue number 0 −360 to 360 degrees to rotate the hue.
--saturation number 0 −100 to 100.
--lightness number 0 −100 to 100.

Simple example

cchef image-hue-saturation-lightness --in-file photo.png --hue 30 --saturation 20 -o tweaked.png

Image Opacity

Multiplies every pixel's alpha channel by a percentage. Pixel-identical to CyberChef for lossless formats.

Option Type Default Notes
--opacity number 100 0–100; the alpha of each pixel is scaled by this fraction.

Simple example

cchef image-opacity --in-file photo.png --opacity 50 -o faded.png

Invert Image

Inverts the colors of an image (each RGB channel becomes 255−value; alpha is unchanged). Pixel-identical to CyberChef for lossless formats.

Takes no options.

Simple example

cchef invert-image --in-file photo.png -o inverted.png

Normalise Image

Stretches each color channel to the full 0–255 range (auto-levels). Ported from Jimp's normalize. Pixel-identical to CyberChef for lossless formats. Takes no options.

Simple example

cchef normalise-image --in-file photo.png -o normalised.png

Optical Character Recognition

Reads text out of an image.

Option Type Default Notes
--show-confidence boolean true Prefix the text with the mean word confidence.
--ocr-engine-mode option LSTM only Tesseract only, LSTM only or Tesseract/LSTM Combined.

Requires tesseract. This is the one operation cchef does not perform itself. CyberChef runs Tesseract compiled to WebAssembly in the browser; the only cgo-free way to do that from Go is to host the WebAssembly module, and the one library that did so is unmaintained and several times slower. Shelling out to the installed engine is what keeps cchef a single static binary with no cgo. Install it with brew install tesseract (macOS) or apt install tesseract-ocr (Debian/Ubuntu); without it the operation fails with a message saying so. Everything else in cchef works regardless.

Because it is the same engine and the same eng language data, the recognized text matches CyberChef's. The confidence figure is the mean confidence of the recognized words.

Tesseract only and Tesseract/LSTM Combined need the legacy engine, which Tesseract 5 no longer ships in its default eng.traineddata — those modes fail with the engine's own message unless legacy training data is installed. LSTM only, the default, is unaffected.

Simple example

cchef optical-character-recognition --in-file scan.png

Output:

Confidence: 96%

Hello World

Complex example

Just the text, with no confidence line, ready to pipe onward:

cchef optical-character-recognition --in-file scan.png --show-confidence=false |
  cchef to-base64

Output:

SGVsbG8gV29ybGQK

Play Media

Validates that the input is an audio or video file (by magic bytes) and outputs it. Ported from CyberChef's Play Media; there is no browser <audio>/<video> preview, so the validated bytes are passed through. A non-media input is rejected.

Option Type Default Notes
--input-format option Raw How to read the input: Raw, Base64 or Hex.

Simple example

Save recovered media to a file (raw passthrough):

cchef play-media --in-file sound.wav -o recovered.wav

Complex example

Emit a base64 data: URI for the detected media type:

cchef from-hex -i "524946460000000057415645" | cchef play-media --data-uri

Output:

data:audio/x-wav;base64,UklGRgAAAABXQVZF

Remove EXIF

Removes the EXIF metadata segment from a JPEG image, returning the stripped bytes. It splits the JPEG into segments and drops the APP1 Exif segment. If the image has no EXIF data it is returned unchanged; non-JPEG input is rejected with Could not remove EXIF data from image: Given data is not jpeg.

Takes no options. Save the result with -o or a redirect.

Simple example

Strip EXIF and confirm none remains by piping into Extract EXIF:

cchef remove-exif --in-file photo.jpg | cchef extract-exif

Output:

Found 0 tags.

Render Image

Validates that the input is an image (jpg/jpeg, png, gif, webp, bmp, ico) and outputs it. Ported from CyberChef's Render Image; the browser <img> preview is passed through unchanged. A non-image input is rejected with Invalid file type.

Option Type Default Notes
--input-format option Raw How to read the input: Raw, Base64 or Hex.

Use the global --preview flag to see the image inline, or --data-uri for a data: URI.

Simple example

Validate and save an image (raw passthrough):

cchef render-image --in-file photo.png -o out.png

Complex example

Emit a base64 data: URI (here from a 1×1 GIF):

cchef from-hex -i "47494638396101000100" | cchef render-image --data-uri

Output:

data:image/gif;base64,R0lGODlhAQABAA==

Render PDF

Validates that the input begins with the %PDF signature and outputs it. Ported from CyberChef's Render PDF; there is no browser <iframe> preview, so the validated bytes are passed through. Input that is not a PDF is rejected with Input does not appear to be a PDF file.

Option Type Default Notes
--input-format option Base64 How to read the input: Base64 or Raw.

Simple example

Validate and save a PDF (raw passthrough):

cchef render-pdf --input-format Raw --in-file report.pdf -o out.pdf

Complex example

Emit a base64 data: URI:

cchef render-pdf --input-format Raw --data-uri -i "%PDF-1.7 hi"

Output:

data:application/pdf;base64,JVBERi0xLjcgaGk=

Resize Image

Resizes an image to a target width and height, optionally as a percentage or preserving the aspect ratio. Ported from Jimp's resize/scaleToFit with all five resampling algorithms.

Option Type Default Notes
--width number 100 Target width (pixels, or percent when Unit type is Percent).
--height number 100 Target height.
--unit-type option Pixels Pixels or Percent (of the source size).
--maintain-aspect-ratio boolean false Scale to fit within Width×Height without distortion.
--resizing-algorithm option Bilinear See the note under the operation table.

Simple example

cchef resize-image --in-file photo.png --width 320 --height 240 -o small.png

Complex example

Halve the size using percent units and nearest-neighbour sampling:

cchef resize-image --in-file photo.png --width 50 --height 50 --unit-type Percent --resizing-algorithm "Nearest Neighbour" -o half.png

Rotate Image

Rotates an image by a number of degrees (Jimp's rotate). Rotations that are a multiple of 90° are pixel-identical to CyberChef; other angles are approximate (see the note above) — the output canvas is sized with CyberChef's expansion formula but the interior pixels differ.

Option Type Default Notes
--rotation-amount-degrees number 90 Positive or negative. Multiples of 90 relocate pixels exactly and resize the canvas; other angles expand the canvas and fill the corners with transparency.

Simple example

cchef rotate-image --in-file photo.png --rotation-amount-degrees 90 -o rotated.png

Scatter chart

Plots two-variable data as individual points. Input is one x y record per line; output is SVG.

Option Type Default Notes
--record-delimiter option Line feed Line feed or CRLF.
--field-delimiter option Space Space, Comma, Semi-colon, Colon or Tab.
--use-column-headers-as-labels boolean true Take the axis labels from the first record.
--x-label string "" Used when headers are not taken as labels.
--y-label string "" Used when headers are not taken as labels.
--colour string black Point color. Any CSS color.
--point-radius number 10 Radius of each point.
--use-colour-from-third-column boolean false Read each point's color from a third field.

The axes extend a tenth of the data's span past it at each end, so points are never drawn on the axis lines.

Simple example

printf '100 100\n200 200\n300 300' | cchef scatter-chart --point-radius 5 -o scatter.svg

Complex example

Color each point from a third column:

printf '1,2,red\n3,4,blue\n5,9,green' |
  cchef scatter-chart --field-delimiter Comma \
    --use-colour-from-third-column --point-radius 4 \
    --x-label x --y-label y -o scatter.svg

Series chart

Draws one line graph per named series over a shared x axis. Input is one series x value record per line; output is SVG.

Option Type Default Notes
--record-delimiter option Line feed Line feed or CRLF.
--field-delimiter option Space Space, Comma, Semi-colon, Colon or Tab.
--x-label string "" Label under the x axis.
--point-radius number 1 Radius of the pip drawn at each value.
--series-colours string mediumseagreen, dodgerblue, tomato Comma-separated CSS colors, cycled across the series.

Series and x values keep the order they first appear in, and each series gets its own y axis scaled to its own range. A series with no value at some x simply skips that point rather than drawing through the gap.

Simple example

printf 'a 1 10\na 2 20\nb 1 5\nb 2 25' | cchef series-chart -o series.svg

Complex example

Comma-separated input with a labelled axis and custom colors:

printf %s "$(cat metrics.csv)" |
  cchef series-chart --field-delimiter Comma \
    --x-label "week" --point-radius 3 \
    --series-colours "tomato, steelblue" -o series.svg

Sharpen Image

Sharpens an image with an unsharp mask. Ported from CyberChef's Sharpen Image, which builds the mask from a Gaussian blur (Jimp's gaussian) and adds it back where the local luminance difference exceeds a threshold. Pixel-identical to CyberChef for lossless formats.

Option Type Default Notes
--radius number 2 Gaussian blur radius used to build the mask.
--amount number 1 Strength the mask is added back with.
--threshold number 10 0–100; only sharpen where the luminance difference is at least this percent.

Simple example

cchef sharpen-image --in-file photo.png --radius 2 --amount 1.5 --threshold 5 -o sharp.png

Split Colour Channels

Splits an image into three PNGs — its red, green and blue channels, each with the other two channels zeroed and the original alpha kept. Pixel-identical to CyberChef.

This operation has no options. It is the one operation that produces several files rather than a single output, so it writes into a directory given with --out-dir instead of to stdout or -o:

cchef split-colour-channels --in-file photo.png --out-dir ./channels
# ./channels/red.png, ./channels/green.png, ./channels/blue.png

Without --out-dir the operation fails, since there is nowhere to put the three files. For the same reason it cannot be chained: it has to be the last step of a recipe.

Complex example

Split every image in a directory. Each input's channels go into their own subdirectory, named after the input file, so the results cannot collide:

cchef split-colour-channels --in-dir ./photos --out-dir ./channels
# ./channels/sunset/red.png, ./channels/sunset/green.png, ...