CLI Scripting
witan pptx exec is the main presentations interface for agents. The CLI sends the deck and script to the configured Witan API, which runs the script inside a sandboxed, headless Office.js-compatible PowerPoint runtime.
Use it when a task needs to inspect, create, edit, export, or verify a deck from code.
Command
witan pptx exec <file.pptx> [flags]
Provide exactly one code source: --code, --script, --stdin, or --expr.
witan pptx exec deck.pptx --expr 'PowerPoint.run(async context => {
const count = context.presentation.slides.getCount();
await context.sync();
return count.value;
})'
For multiline scripts, use --stdin:
witan pptx exec deck.pptx --stdin <<'JS'
return await PowerPoint.run(async context => {
const slide = context.presentation.slides.getItemAt(0);
slide.shapes.addTextBox("Updated", { left: 60, top: 60, width: 300, height: 80 });
await context.sync();
return slide.id;
});
JS
Flags
| Flag | Default | Description |
|---|---|---|
--code <ts/js> |
- | Inline TypeScript or JavaScript source. |
--script <path> |
- | Path to a TypeScript or JavaScript file. |
--stdin |
false |
Read TypeScript or JavaScript source from stdin. |
--expr <expr> |
- | Single-expression shorthand; wraps as return (<expr>);. |
--input-json <json> |
{} |
JSON value exposed as the global input. |
--input-file <key=@path> |
- | Add a local PNG/JPEG file to input as a data:image/...;base64,... URI. Repeatable. |
--locale <name> |
Environment-derived | Execution locale. Falls back to WITAN_LOCALE, then LC_ALL, LC_MESSAGES, and LANG. |
--stdin-timeout-ms <ms> |
2000 |
Maximum time to wait for EOF when reading --stdin; 0 disables. |
--timeout-ms <ms> |
0 |
Execution timeout override. 0 uses the server default. |
--max-output-chars <n> |
0 |
Stdout capture limit override. 0 uses the server default. |
--create |
false |
Create a new .pptx file instead of opening an existing file. |
--save |
false |
Write returned presentation bytes to the target path. |
--json |
false |
Use witan pptx --json exec ... to print the full response envelope. |
Runtime Model
Scripts usually start with PowerPoint.run:
return await PowerPoint.run(async context => {
const presentation = context.presentation;
const slide = presentation.slides.getItemAt(0);
const shapeCount = slide.shapes.getCount();
await context.sync();
return shapeCount.value;
});
OfficeExtension.ClientResult values, such as getCount(), should be read after await context.sync(). In Witan's headless runtime, load(...) and sync() are compatibility calls rather than network round trips: load(...) records requested properties, and sync() provides the Office.js sequencing point while resolving against the in-memory presentation model.
Creating Decks
Use --create with a path that does not exist:
witan pptx exec new-deck.pptx --create --save --stdin <<'JS'
return await PowerPoint.run(async context => {
const slide = context.presentation.slides.getItemAt(0);
slide.shapes.addTextBox("Created", { left: 60, top: 60, width: 300, height: 80 });
await context.sync();
return true;
});
JS
PowerPoint.createPresentation(...) is intentionally not implemented. File creation belongs to the CLI because the runtime runs headlessly inside the open presentation session.
Saving
Without --save, writes are in-memory for the request. Use --save when the modified .pptx should be written back to disk.
For uploaded presentations, updated bytes are returned only when writes are detected. For --create --save, the created file bytes are returned when execution succeeds.
Input Files
Use --input-file for image authoring:
witan pptx exec deck.pptx --save \
--input-file logo=@./logo.png \
--stdin <<'JS'
return await PowerPoint.run(async context => {
const slide = context.presentation.slides.getItemAt(0);
slide.shapes.addPicture(input.logo, {
left: 54,
top: 42,
width: 120,
height: 60
});
await context.sync();
return true;
});
JS
Chart Extensions
Witan adds chart APIs to the Office.js PowerPoint object model:
const shape = slide.shapes.addChart(PowerPoint.ChartType.waterfall, [
["Step", "Amount"],
["Start", 120],
["Growth", 45],
["Churn", -18],
["End", 147]
], { left: 72, top: 100, width: 600, height: 340 });
const chart = shape.getChart();
chart.title.text = "Revenue Bridge";
chart.series.getItemAt(0).showConnectorLines = true;
Charts are real PowerPoint chart parts with embedded workbook data. See Charts and pptx API.
Sandbox
- No filesystem access.
- No network access.
- No static or dynamic imports.
- Top-level
awaitis supported. - Use
print(...)for progress output. - The script return value is serialized as JSON.
Verification
After visual edits, render the affected slide:
witan pptx render deck.pptx --slide 3 -o slide-3.png
For regression checks:
witan pptx render deck.pptx --slide 3 -o before.png
# ... edit ...
witan pptx render deck.pptx --slide 3 --diff before.png -o diff.png
See Render for rendering behavior and limits.