CLI reference.
14 commands, 50+ operation types, 9 chart types, structured errors, and deterministic output.
Commands
All commands follow the pattern slides <command> [options]. Run slides <command> --help for per-command details.
| Command | Description |
|---|---|
extract | Extract template contracts from a .pptx |
render | Render a deck from slides.json (plan + ops) |
apply | Apply an ops patch to an existing deck |
inspect | Inspect deck structure as JSON |
find | Search text across slides |
plan-inspect | Inspect a slides.json document with pagination |
validate | Run OOXML validation |
lint | Lint deck against design profile |
qa | Combined gate: validate + lint + assets |
edit | Text find-and-replace |
transform | Transform a slide to a different archetype |
repair | Conservative repair pass |
docs | Print runtime discovery contract |
version | Print contract version |
Global flags
Available on every command:
| Flag | Effect |
|---|---|
--fields | Comma-separated field mask. Only include these fields in JSON output. See Field masks. |
--ndjson | Emit list outputs as newline-delimited JSON instead of arrays. |
--compact | Strip null and empty values from JSON output. Reduces size 30-50%. |
--verbose | Print full stdout payloads. Default is quiet when writing to files. |
Field masks
--fields accepts a comma-separated list of dot-separated paths. Only matching fields appear in the output. Dot notation traverses into arrays, so slides.title extracts the title from each slide object.
# top-level field
slides inspect deck.pptx --fields summary --compact
# nested scalar inside a dict
slides inspect deck.pptx --fields summary.slide_count --compact
# project specific keys from each slide (array traversal)
slides inspect deck.pptx --fields slides.slide_index,slides.title --compact --page-size 5
# double-nested: project into shapes inside slides
slides inspect deck.pptx --fields slides.slide_index,slides.shapes.kind,slides.shapes.name \
--compact --page-size 1
Each command has an allowlist of valid fields. To discover them:
# list all field masks for all payloads
slides docs fields
# list fields for a specific payload
slides docs fields:inspect
slides docs fields:lint
slides docs fields:find
Requesting a field not in the allowlist returns a clear error with the valid options listed.
slides extract
slides extract <source.pptx> --output-dir <dir> [options]
| Option | Description |
|---|---|
source | Template or sample .pptx file (required) |
--output-dir | Output directory for artifacts (required) |
--base-template-out | Also write a clean base template |
Writes template_layout.json, content_layout.json, archetypes.json, resolved_manifest.json, slides_manifest.json, slide_analysis.json, and optionally base_template.pptx and icons/.
See How it works: Extraction for what each artifact contains and how they feed into the build step.
slides render
slides render --slides-json @slides.json --output deck.pptx [options]
| Option | Description |
|---|---|
--slides-json | Slides document JSON or @file (required) |
--template | Template PPTX path |
--output | Output PPTX path |
--profile | Design profile JSON file |
--icon-pack-dir | Custom icon directory |
--dry-run | Plan operations without applying |
--no-transaction | Disable rollback on failure |
--non-deterministic | Disable deterministic ZIP save |
slides apply
slides apply [input.pptx] --ops-json @ops.json --output out.pptx
Applies an OperationBatch to an existing deck (or a blank deck if input is omitted). Supports --dry-run, --profile, --icon-pack-dir, and the same transaction/determinism flags as render.
slides inspect
slides inspect deck.pptx [options]
| Option | Description |
|---|---|
--out | Write inspect JSON to file |
--summary | Print deck summary only |
--placeholders N | List placeholders for slide N |
--fingerprint | Print deterministic SHA-256 fingerprint |
--page-size N | Paginate output (N slides per page) |
--page-token T | Continue from page token |
--page-all | Emit all pages at once |
slides find
slides find deck.pptx --query "pricing" [options]
Searches for text across all slides. Returns matching shapes with slide/shape UIDs for targeted edits. Supports --limit, --out, and pagination flags.
slides validate, lint, qa
# basic validation
slides validate deck.pptx
# strict validation
slides validate deck.pptx --deep --fail-on-error
# design lint
slides lint deck.pptx --profile dp.json --out lint.json --compact
# combined gate
slides qa deck.pptx --profile dp.json --out qa.json --compact
validate checks OOXML structure. lint checks against the design profile (fonts, colors, overlap, contrast). qa runs both plus asset checks. All accept --slides-json for additional context.
slides edit, transform, repair
# text replacement
slides edit deck.pptx --query "old text" --replacement "new text" \
--slide-uid "abc123" --output deck.pptx
# archetype transform
slides transform deck.pptx --slide-uid "abc123" --to timeline \
--output deck.pptx
# conservative repair
slides repair deck.pptx --output deck.pptx
edit targets by slide UID, shape UID, or both. transform converts a slide to a different archetype. repair applies safe fixes without changing content.
slides docs
# full markdown docs
slides docs
# machine-readable contract as JSON
slides docs json
# specific method
slides docs method:render
# specific schema
slides docs schema:slides-document
slides docs schema:operation-batch
# field mask discovery
slides docs fields
slides docs fields:inspect
Runtime schema discovery. The schemas come from the same Pydantic models that validate input, so they can't drift from the implementation. fields and fields:<payload> list the allowed --fields values for each command.
Operations reference
Operations are JSON objects in an OperationBatch. Each has an op field and type-specific parameters. All geometry values are in inches.
Content
op | Required | Optional |
|---|---|---|
add_slide | layout_index (default 6), layout_name | |
add_text | slide_index, text, left, top, width, height | font_size (20), bold, font_name, font_color |
add_image | slide_index, path, left, top | width, height |
add_table | slide_index, rows, left, top, width, height | font_size |
add_notes | slide_index, text | |
add_media | slide_index, path, left, top, width, height | mime_type, poster_path |
replace_text | slide_index, old, new | |
delete_slide | slide_index | |
move_slide | from_index, to_index |
The rows parameter for add_table is a nested array: [["Header A", "Header B"], ["row1a", "row1b"]]. Allow about 0.5 inches per row for height.
Icons
op | Required | Optional |
|---|---|---|
add_icon | slide_index, icon_name, left, top | size (0.75), color (6-digit hex) |
Icons are SVG-based vector shapes inserted as native PowerPoint objects (not images). Two built-in icons ship with agent-slides: generic_circle and generic_square.
Templates can contain additional icons. During slides extract, vector shapes found on template slides are exported to an icons/ directory. These become available to add_icon when you set icon_pack_dir in the design profile.
Name matching is case-insensitive and partial. "circle" matches generic_circle. "Target" matches icon_Target.svg from the template pack.
// place a circle icon, white fill, at position (2, 1.5)
{
"op": "add_icon",
"slide_index": 0,
"icon_name": "circle",
"left": 2.0,
"top": 1.5,
"size": 0.75,
"color": "FFFFFF"
}
To see which icons are available for a given template, check the icons/ directory after extraction. The design profile's icon_pack_dir field points to this directory.
Shapes
op | Required | Optional |
|---|---|---|
add_rectangle | slide_index, left, top, width, height, fill_color | border_color, border_width |
add_rounded_rectangle | (same as rectangle) | corner_radius, borders |
add_oval | (same as rectangle) | borders |
add_line_shape | slide_index, x1, y1, x2, y2 | color, line_width |
Charts
All chart ops require slide_index, left, top, width, height.
op | Data format | Styles |
|---|---|---|
add_bar_chart | categories + series | clustered, stacked, percent_stacked |
add_line_chart | categories + series | line, line_markers, stacked, stacked_markers, percent_stacked, percent_stacked_markers |
add_pie_chart | categories + series | pie, exploded, pie_of_pie, bar_of_pie |
add_area_chart | categories + series | area, stacked, percent_stacked |
add_doughnut_chart | categories + series | doughnut, exploded |
add_radar_chart | categories + series | radar, filled, markers |
add_scatter_chart | series (xy tuples) | markers, line, line_no_markers, smooth, smooth_no_markers |
add_bubble_chart | series (xyz tuples) | bubble, bubble_3d |
add_combo_chart_overlay | categories + bar_series + line_series |
Series format for category charts: [["Series Name", [1.0, 2.0, 3.0]], ...]
Scatter charts: [["Name", [[x1, y1], [x2, y2]]], ...]
Bubble charts: [["Name", [[x, y, size], ...]], ...]
Chart styling
All require slide_index and chart_index.
op | Key parameters |
|---|---|
update_chart_data | categories, series |
set_chart_title | text |
set_chart_style | style_id (1-48) |
set_chart_legend | visible, position, font_size, include_in_layout |
set_chart_axis_titles | category_title, value_title |
set_chart_axis_options | axis, reverse_order, visible, font_size |
set_chart_axis_scale | minimum, maximum, major_unit, number_format |
set_chart_data_labels | enabled, show_value, show_category_name |
set_chart_data_labels_style | position (use snake_case: outside_end), font_size |
set_chart_plot_style | vary_by_categories, gap_width, overlap, plot_area_x/y/w/h (0–1 fractions) |
set_chart_series_style | series_index, fill_color_hex |
set_chart_series_line_style | series_index, line_color_hex, line_width_pt |
set_chart_secondary_axis | enable, series_indices |
set_line_series_marker | series_index, style, size |
set_chart_series_trendline | series_index, trend_type |
Layout and placeholders
op | Parameters |
|---|---|
set_slide_background | slide_index, color_hex |
set_placeholder_text | slide_index, placeholder_idx, text |
set_title_subtitle | slide_index, title, subtitle |
set_semantic_text | slide_index, role, text |
set_core_properties | title, subject, author, keywords |
set_placeholder_image | slide_index, placeholder_idx, path + crop/position |
update_table_cell | slide_index, table_index, row, col, text, font_size |
Execution semantics
Operations execute in array order. By default, execution is transactional: if any operation fails, all prior changes are rolled back. Set --no-transaction to continue past failures.
The operation report shows what happened:
{
"ok": true,
"dry_run": false,
"applied_count": 5,
"failed_index": null,
"events": [
{"index": 0, "op": "add_slide", "status": "applied", "duration_ms": 12},
{"index": 1, "op": "add_text", "status": "applied", "duration_ms": 3}
]
}
On failure, ok is false, failed_index points to the broken operation, and the detail field on the failed event contains a structured error.
Error format
All errors include a machine-readable code, a description, and a suggested fix:
{
"code": "INVALID_BAR_STYLE",
"message": "Unknown bar chart style 'invalid_style'",
"suggested_fix": "Use one of: clustered, stacked, percent_stacked"
}
Error codes are stable across versions. Common codes:
| Code | Meaning |
|---|---|
INVALID_SLIDE_INDEX | Slide index out of range |
INVALID_LAYOUT_INDEX | Layout index out of range |
INVALID_LAYOUT_NAME | Layout name not found in template |
IMAGE_NOT_FOUND | Image file does not exist |
INVALID_TABLE | Empty rows or inconsistent column counts |
INVALID_COLOR_HEX | Not a valid 6-digit hex color |
INVALID_FONT_SIZE | Font size outside 6-72 range |
PLACEHOLDER_NOT_FOUND | Placeholder index not found on slide |
SEMANTIC_ROLE_NOT_FOUND | No placeholder matches the role |
UNKNOWN_OPERATION | Unrecognized op string |
The full error code catalog is available via slides docs json.
Exit codes
| Code | Meaning |
|---|---|
0 | Success |
2 | Operation batch failed |
3 | Validation error (with --fail-on-error) |
4 | Validation warning (with --fail-on-warning) |
5 | Lint failed |
6 | Edit found no matches |
9 | QA failed |
Deterministic output
By default, output is fully deterministic. Timestamps are zeroed, GUIDs are derived from content hashes, and ZIP member order is sorted. Two renders with the same input produce byte-identical output.
slides inspect --fingerprint returns a SHA-256 hash over the deterministic bytes. Use it in CI to verify that a refactor didn't change output.
Pass --non-deterministic to disable this (rarely needed).