How to Use IronPPT with Claude Code
A training company issues a PowerPoint handout for every session of its C# course. Each module has an outline file with the topics, the points under each topic, code samples and the occasional warning, and a house style file fixes the typeface, size and position of every kind of text. When the decks are assembled by hand, one wrong font or one overlapping text box can go unnoticed until a trainee prints the handout. Claude Code, Anthropic's software agent, runs in terminals, VS Code, JetBrains, desktop applications and on the web. In each environment, it reads repositories, modifies files and executes commands.
IronPPT is a .NET library that creates and edits PowerPoint files without Office Interop. AddText adds text to a slide, as the add text guide shows, and TextStyle sets its weight, font and size. Four tested prompts set up Claude Code and have it build the handout generator. The IronPPT text behaviors that each prompt depends on are recorded beside them.
Open a terminal in the project folder, run claude, and enter /model opusplan before the first prompt. A path that starts with @ attaches that file to the request.
Install IronPPT from NuGet, version 2026.10.1, in TrainingHandouts.csproj.
Then turn Program.cs into a smoke test built from @course/module-03-async.json.
Program.cs runs these steps in order:
1. Applies the key, then prints the value of License.IsLicensed.
2. Adds the module's title value to the first slide with Slide.AddText.
3. Saves the deck as out/smoke.pptx, creating out/ if it's missing.
4. Loads out/smoke.pptx again and prints how many slides it has.
5. Lists every text box on each slide, with its text in quotes.
The key is in the IRONPPT_LICENSE_KEY environment variable, and these rules cover it:
- Program.cs reads the variable at startup and copies the value into License.LicenseKey.
- Never log the key, print it, or write it to a file.
- Don't run any command that lists environment variables.
- If you need to check the variable, tell me only whether it's set.
Run the program once and tell me what it printed.
Minimal Workflow (5 steps)
- Download the C# PowerPoint library from NuGet
- Open Claude Code from the project folder and set the model with /model
- Record IronPPT's measured text rules in CLAUDE.md so that every session loads them
- Request a generator that positions every text box and takes each style from the house style file
- Check the saved slide XML against the style file before a handout goes to print
What does Claude Code do in a .NET presentation project?
The agent writes the generator, reads the outline files, builds one deck per module and checks every saved deck against the style file. When a check fails, it reads the report it produced, corrects the generator and runs it again. The developer decides the house style and the text of each slide.
The first prompt names the IronPPT package and its version. An agent left to choose a package name can install a package that an attacker registered under a name that AI tools generate but no real package uses. This attack is known as slopsquatting.
How do you set up Claude Code?
Install Claude Code and sign in by following Anthropic's quickstart. Setup is complete when claude starts in a terminal and responds.
How do you set up a project Claude Code can work in?
Give the agent real inputs before the first prompt. The test fixture is a .NET 9 console application with a course folder that holds two module outlines and the house style file. The module 3 outline covers async and await in four topics, and the module 4 outline covers LINQ in three. The style file defines seven text roles, each with a typeface, a size, a weight, an alignment and a box in points.
CLAUDE.md is loaded at the start of each session, so rules written there apply to every later prompt. The second prompt creates the file and a read-only reviewer for the generator code.
Write a CLAUDE.md for this repo.
Its Presentations section holds these rules for every later session:
- IronPPT is the only presentation library. Don't add the Open XML SDK or any other.
- Keep the IronPPT version that TrainingHandouts.csproj references now.
- Look up IronPPT member names in docs/IronPPT.xml before you use them.
- course/ holds the inputs. Leave every file in it as it is.
- Program.cs saves decks to out/, and each saved deck is opened again and checked.
Copy IronPPT.xml into docs/ now, from the ironppt 2026.10.1 package in the local NuGet cache.
It's under lib/netstandard2.0. If it's missing, tell me and keep going.
Next, add a subagent at .claude/agents/handout-layout-reviewer.md.
Its tools are Read, Grep and Glob, and no others.
It reviews Handouts/ and answers four questions:
- Which IronPPT types and members does the code use?
- Which of those are missing from docs/IronPPT.xml?
- Which text boxes reach a slide without a Position, Width and Height?
- Which style settings in the code does CLAUDE.md list as lost on save?
I'll add IronPPT's measured text rules to CLAUDE.md myself before the first review.
When you're done, tell me whether the XML copy worked.
Claude Code detects a new subagent file without a restart, provided the .claude/agents folder existed when the session started. Create that folder in the repository before launching the session. For guides beyond the member list, IronPPT lists its documentation for agents in llms.txt.
Which IronPPT text rules belong in CLAUDE.md?
Each line comes from a probe run with and without a license key, in which every saved deck was read back from its slide XML. Paste the block under the Presentations section.
These text rules were measured on IronPPT 2026.10.1:
- IronPPT doesn't read IRONPPT_LICENSE_KEY. Assign License.LicenseKey before the first save.
- Without a key, decks build and load, but Save throws LicensingException and writes no file.
- LicensingException isn't public, so catch (LicensingException) fails with CS0122.
- Match that exception by its type name instead.
- new PresentationDocument() already has one slide, holding an empty title and subtitle.
- A slide is 720 by 540 points.
- Slide.AddText writes a 150 by 100 point box with no position. Two calls overlap.
- Give every TextBox a Position, Width and Height. All three are in points.
- Set the typeface with Font.LatinFont. Font.FontFamily is never written to the file.
- Font.FontSize is in points.
- Align with Paragraph.Style = new ParagraphStyle { Alignment = TextAlignmentTypeValues.Center }.
- Paragraph.Alignment and Paragraph.SetAlignment write left alignment, even for Center or Right.
- Leave TextStyle.Color unset. Each colored run fails Open XML validation.
- new Color(r, g, b) makes Save throw NullReferenceException.
- An Underline writes no u attribute, so nothing is underlined.
- A line break inside one AddText string stays inside one run. Use a Paragraph per line.
- After a reload, font sizes, positions and box sizes read back at 12700 times the XML value.
- It also reports every alignment as Left after a reload.
- So check fonts, sizes, positions and alignment in the slide XML, not through IronPPT's reader.
IronPPT reads an environment variable named IronPPT.LicenseKey by itself, and the probe found that it ignores IRONPPT_LICENSE_KEY.
Where does IronPPT place text on a slide?
Slide.AddText writes the text into a new shape that is 150 by 100 points and has no position. The add text guide's own screenshot shows the result on the first slide, where "Hello from IronPPT!" wraps over three lines in a narrow box at the top left. Every further AddText call on the same slide writes another shape of the same size with no position, so the shapes overlap.
A handout needs each kind of text in a fixed place. A TextBox accepts a Position, a Width and a Height, all in points, and IronPPT writes them to the slide as offsets and extents. The slide itself is 720 by 540 points, the standard 4 by 3 size, so a style file written for a widescreen deck does not fit.
The title slide of the module 3 handout from the test run shows the three title boxes, each placed and sized from the style file.

Slide 1 of the module 3 handout as IronPPT saved it in the test run. It is drawn to scale from the slide XML in the typefaces and sizes it names. The box outlines come from the drawing script, which is not a PowerPoint rendering.
Every text box IronPPT writes is a body placeholder. The slide master's body style, which body placeholders follow, defines a bullet character and a 32-point default size.
Which text styles does IronPPT write to the file?
IronPPT writes bold, italic and the font size to the file as set. The probe set Font.FontFamily to Consolas and found no typeface in the run properties, while Font.LatinFont wrote the typeface.
Alignment depends on which member sets it. Paragraph.Alignment and Paragraph.SetAlignment both left a centered paragraph aligned to the left. Setting Paragraph.Style to a ParagraphStyle with TextAlignmentTypeValues.Center wrote the centered alignment. The TextAlignmentTypeValues enum is declared in the global namespace, outside IronPPT.Enums.
Every colored run, named or hexadecimal, failed the Open XML SDK validator, because IronPPT writes the alpha and channel values beside the color instead of inside it. The Color(r, g, b) constructor made Save throw NullReferenceException. An Underline wrote the underline line properties but not the attribute that switches underlining on. IronPPT's own skill.md uses SetAlignment, a colored TextStyle and an underline in its samples, so an agent that copies those samples gets the same results.
How do you prompt for IronPPT code that compiles?
Request the generator and its checker in one prompt, and allow plan mode to complete the design before any file changes. Switch to plan mode with Shift+Tab before sending the prompt. With opusplan selected, Opus writes the plan and Sonnet implements it once the plan is approved.
Build Handouts/HandoutBuilder.cs and its checker, Handouts/HandoutChecker.cs.
Have Program.cs run both.
Every JSON file in course/ except handout-style.json is a module.
HandoutBuilder follows these rules:
- Each module becomes out/<id>-handout.pptx.
- Another method builds a deck without saving it.
- Each box takes font, size, weight, alignment and box from the style role of the same name.
- Slide 1 is the document's own first slide, with course, title and trainer boxes.
- Each topic then gets a slide, in module file order.
- The title box reads "Module <module>: <title>".
- The trainer box reads "<trainer>, <date>", with the date unchanged.
Topic slides get these boxes:
- heading, the topic heading.
- point, one paragraph per point.
- code, if any, one paragraph per line, leading spaces kept.
- warning, if any.
HandoutChecker reads each saved deck's slide XML from the zip:
- It writes out/handout-check.csv, one row per paragraph, and skips empty shapes.
- It infers roles from the module file and box order.
- One method checks one deck file and returns its rows.
- Its columns are Module, Slide, Role, Text, Typeface, SizePt, Bold, Italic and Align.
- Then come X, Y, Width, Height and Match.
- Align is left, center or right. No algn attribute means left.
- Match is yes when text matches the module file and the rest matches the style file.
Run the program and tell me how many rows say no per module.
Then show me what the handout-layout-reviewer subagent finds.
Two parts of the prompt keep the handouts correct.
- The style file as the single source: every typeface, size, weight, alignment and box comes from one file, so the checker can compare each paragraph with a value the trainer wrote down.
- A checker that reads the XML: after a reload, IronPPT reports each font size, position and box size at 12,700 times the value in the slide XML, and every alignment as left. A check built on IronPPT's reader would fail correct decks.
Can IronPPT handout code be tested without a license key?
Building a deck in memory and loading a saved deck both run without a key. Only the save needs one, so a test project can check the slide structure and the checker on a build agent that has no key.
Add an xUnit project, TrainingHandouts.Tests, for net9.0 in a folder of its own.
Keep that folder out of the TrainingHandouts.csproj build, and don't add a solution file.
Copy course/ and out/module-03-handout.pptx into the test output folder as test data.
The tests cover these cases:
- HandoutBuilder makes 5 slides for module-03 and 4 for module-04, with no save.
- The second code line on the last module-04 slide keeps its 4 leading spaces.
- Saving any deck with no key applied throws an exception whose type name is LicensingException.
- That failed save leaves no file at the target path.
- HandoutChecker finds 0 rows marked no in the copied deck.
- A changed heading typeface in a copy of that deck's slide XML gives exactly 1 row marked no.
Run dotnet test on TrainingHandouts.Tests once.
Use a child process with IRONPPT_LICENSE_KEY removed.
Tell me how many tests passed.
What should you verify before trusting generated IronPPT code?
Include the following checks in the review.
- The build:
dotnet buildrejects a member that does not exist. The shipped IronPPT.xml also documents members that compile and still lose their value on save, so a successful build proves only that the names exist. - The slide XML: compare the typeface, size, alignment and box of every paragraph with the style file.
- One printed handout: before a course starts, print one deck and confirm that no text box overlaps another.
For a complete IronPPT task with fixed pass criteria that can be rerun, see the AI coding assistants guide.
What did the prompts produce in a real run?
Claude Code ran the four prompts in one session, in order. The rules block went into CLAUDE.md before prompt 3. No code was edited by hand.
- Before the run, the repository held the course folder and a one-line Program.cs, with no package reference.
- The Quickstart deck had 1 slide with three text boxes, two of them the empty title and subtitle placeholders.
- CLAUDE.md received the five project rules, and the subagent file listed only the Read, Grep and Glob tools.
- After prompt 3, the module 3 handout had 5 slides and the module 4 handout had 4.
- All 26 text boxes had the position and size that the style file gives.
- In our check of the slide XML, all 38 paragraphs matched the style file in typeface, size, weight and alignment.
- The checker's report held 38 rows, and no row was marked no.
- Claude Code's own summary of prompt 3 gave 37 rows, one fewer than the report file held.
- The code line with four leading spaces and the accented trainer name appeared on the slides unchanged.
- Both handouts passed the Open XML SDK validator with 0 errors.
- The generator created every box as a positioned TextBox and never called AddText.
- The subagent found no text box without a position and no setting that the rules list as lost.
- 6 of 6 tests passed in a process without IRONPPT_LICENSE_KEY, and again in a fresh clone.
- A Release run in a fresh clone produced the same two handouts and the same 38 rows.
- Without a key, the program skipped both modules and wrote a report with a header and no rows.
- The license key appeared in no transcript, session file, or repository file from this run.
- Some steps ran differently from the page. The session ran headless, so the plan appeared in the reply and a typed reply approved it. The run's guard, which kept the agent inside the repository, blocked the plan file that Claude Code tried to save in the user profile.
In the module 3 handout, slide 3 held the second topic, with its two points and three lines of code.

Slide 3 of the module 3 handout as IronPPT saved it in the test run. It is drawn to scale from the slide XML in the typefaces and sizes it names. The box outlines come from the drawing script, which is not a PowerPoint rendering.
The Cursor guide also has the agent write a plan first, which Cursor saves as an editable Markdown file. The ChatGPT Codex guide keeps its deck rules in AGENTS.md, which Codex reads before any work, as this guide does with CLAUDE.md. The Claude Code version, models, timings and test machine for this run are in the shared run record.
Troubleshooting
- Applying License Keys if
SavethrowsLicensingException - Engineering Support Request to report a text style that is missing from the saved file
Questions?
If you have any questions, reach out to support@ironsoftware.com
Curtis Chau holds a Bachelor’s degree in Computer Science (Carleton University) and specializes in front-end development with expertise in Node.js, TypeScript, JavaScript, and React. Passionate about crafting intuitive and aesthetically pleasing user interfaces, Curtis enjoys working with modern frameworks and creating well-structured, visually appealing manuals.