How to Use IronZIP with Cursor

Curtis Chau
Curtis Chau
Updated: October 19, 2026

ClientDrop, the .NET 9 service in this guide, packs each client's document folder into the ZIP the client downloads. It builds those bundles with System.IO.Compression, which has no way to set a password, and compliance now wants every bundle protected with AES-256. The bundle code has to move to IronZIP, and a move made by an AI agent has a less visible risk. IronZIP and System.IO.Compression disagree on details that still compile. System.IO.Compression keeps the folder path of every file it packs and IronZIP's Add keeps only the file name, so two statements from different months can receive the same entry name.

The port uses three Cursor features. A committed project rule names the System.IO.Compression habits to drop, in Plan Mode the agent writes the mapping as a plan before any file changes, and documentation links in the prompts and the rule point the agent to IronZIP's pages. Each ClientDrop bundle is encrypted when it is built, extracted with that password to prove it still holds every file, and opened again with its password when the tests count its entries.

Quickstart
NuGetInstall with NuGet

PM > Install-Package IronZip

Install IronZIP by running the command above in the NuGet Package Manager Console, or search for the package in the NuGet Package Manager.

With ClientDrop open in Cursor, paste this into Agent. Its two mentions attach the bundle class and one client's folder.

@src/ClientDrop/Bundles/BundleBuilder.cs @TestData/clients/C-1042/

Fetch https://ironsoftware.com/zip/csharp/llms.txt first and read it before any edit.
BundleBuilder packs a client folder with System.IO.Compression.
Run dotnet test once and report the result.

Then make these changes:
1. Add the IronZip package, version 2026.10.2, to src/ClientDrop.
2. Give Program.cs an "inspect <zip> [password]" command that opens a bundle with IronZIP.
3. Have inspect print each entry's name, size and whether it is encrypted.
4. Assign License.LicenseKey the value of IRONZIP_LICENSE_KEY.
5. Keep the key out of all output, and don't list the environment variables.
6. Keep BundleBuilder.cs unchanged.

Bundle C-1042 with the current code, run inspect on out/C-1042.zip and show me the output.
Text

The inspect command reads the old bundle and lists seven entries with their folder paths, from contract.pdf at the root to statements/2026-05/statement.pdf, and none of them encrypted.

Leave the license key out of every prompt. In Agent mode, Cursor writes code and executes terminal commands, so a key typed into the conversation can be copied into code or a commit message. Set the IRONZIP_LICENSE_KEY environment variable instead. IronZIP does not read that variable by itself, which is why the prompt has the code assign it to License.LicenseKey. In a probe that set the variable and made no assignment, the save call threw a LicensingException that reads "Production License Required". The license key guide covers the places IronZIP does look on its own, such as an appsettings.json file that Git can ignore.



Which Cursor model should you use for IronZIP work?

Composer is Cursor's own agentic model. The model picker also offers SpaceXAI's Grok models, which Cursor co-developed, and models from OpenAI, Anthropic, Google and other labs. The run in this guide used Grok 4.7. Whichever model you choose, name the files, the tests and the expected counts in the prompt.

How do you give Cursor the IronZIP documentation?

IronZIP's llms.txt is a single page that lists its examples and tutorials with a short summary of each. As of October 2026, the @ menu in Cursor offers the browser, Git diffs, terminals, past chats, files and folders, with no entry for documentation, so the prompt gives IronZIP's documentation as a link.

The port depends on where the folder paths go and when IronZIP checks a password. The next prompt asks Cursor to answer both from the pages and to say when no page covers a point.

@src/ClientDrop/Bundles/BundleBuilder.cs

Your only source is https://ironsoftware.com/zip/csharp/llms.txt plus the example pages it links.
Do not edit files.
List each System.IO.Compression call in BundleBuilder.
Next to each call, name the IronZIP member that would replace it.

Then answer three questions:
1. Does Add keep the folder path of the file it is given?
2. Which call encrypts a new archive with AES-256?
3. For an existing protected archive, is the password checked at the constructor or at extraction?

Cite the page URL behind every answer, and say plainly when no page covers a point.
Text

The pages answer the encryption question in two halves. The password example calls Encrypt with EncryptionMethods.Traditional, and the access example switches the same call to AES-256. No page says what Add does with a folder path. Two pages mislead. The access example says an incorrect password makes the operation fail, which held only for extraction, and the add files example opens an existing ZIP with FromFile, which builds a new archive holding that ZIP as a single entry. The IronZipArchive reference documents members that no example page shows, such as SetPassword and RemoveEncryption.

Please note: IronZIP also publishes a skill file whose frontmatter names it ironzip. Saved as .cursor/skills/ironzip/SKILL.md, it is discovered when Cursor starts, and typing /ironzip in Agent attaches it to one message.

How do you write project rules that encode your IronZIP conventions?

Project rules are .mdc files under .cursor/rules, committed with the code, each one Markdown with a frontmatter block. The rules system skips a plain .md file under .cursor/rules, because such a file has no frontmatter. The description, globs and alwaysApply fields decide when Cursor applies the rule.

This rule is scoped with globs, so Cursor applies it to any request that has a file from the service or its tests in context, and @ironzip-bundles attaches it by name. Several patterns go on one line, separated by commas. Save it as .cursor/rules/ironzip-bundles.mdc.

---
description: Move ClientDrop bundle code from System.IO.Compression to IronZIP
globs: src/ClientDrop/**/*.cs, tests/ClientDrop.Tests/**/*.cs
alwaysApply: false
---

ClientDrop writes bundles with IronZIP and follows these rules:
- Use IronZIP only. The NuGet package and the namespace are both IronZip.
- Remove System.IO.Compression from src/ClientDrop.
- Do not add SharpZipLib, DotNetZip or another archive package.
- IronZIP's docs start at https://ironsoftware.com/zip/csharp/llms.txt.
- Set License.LicenseKey from IRONZIP_LICENSE_KEY.
- Never write a license key or a bundle password into code, tests or logs.
- Encrypt every bundle with EncryptionMethods.AES256 and BundleOptions.Password.
- Open an existing bundle with new IronZipArchive(path, password).
- FromFile, FromFiles and FromDirectory build a new archive instead.
- Do not invent IronZIP members. For a member no page documents, say so and cite the page searched.
Markdown

The FromFile line is there because opening a bundle with FromFile raises no error, and the original bundle stays unchanged.

The rule affects Agent requests only. Per the FAQ on Cursor's rules page, Tab completions ignore rules, and inline edit (Ctrl+K) ignores user rules.

How do you map System.IO.Compression calls to IronZIP?

A rule that only says "use IronZIP" makes the model work out what each call becomes. Each IronZIP result was measured with IronZIP 2026.10.2 on client C-1042, whose folder holds seven documents, three of them named statement.pdf and two named invoice.pdf in different month folders.

System.IO.Compression callExpectedIronZIP
ZipFile.CreateFromDirectorySeven entries, folders keptFromDirectory, shown in the skill file, packed only contract.pdf
CreateEntryFromFile for each fileOne entry per fileAdd stored seven entries under four names, and extraction left four files
Delete and CreateEntryFromFile in update modeThe reissued document keeps its nameReplaceEntry named the new entry after the path it was given, here ZipWork/cursor/repo-baseline/TestData/reissue/C-1042/contract.pdf
ZipFile.OpenRead in the testsEvery entry readableThe AES entries listed, and reading one threw InvalidDataException "unsupported compression method"

On the bundle with duplicate names, ReplaceEntry failed before any rename. It threw ArgumentException "An item with the same key has already been added" over the two invoice.pdf entries. Encryption itself worked. Encrypt with EncryptionMethods.AES256 marked all seven entries as encrypted, and a staged copy of the folder under unique flat names, such as statements_2026-03_statement.pdf, extracted to seven files that matched the originals by SHA-256. The duplicate names are the hardest problem to catch, because a bundle that loses a statement still holds seven entries, so a count check passes while the client downloads four documents.

Append the translations to the rule.

The port translates System.IO.Compression habits this way:
- Add keeps only the file name.
- Copy each file to a staging folder under a name unique in the bundle, and add the copy.
- One such name is statements_2026-03_statement.pdf.
- ReplaceEntry names the new entry after the path it is given.
- To swap a document, Delete the entry and Add a staged copy named like the old entry.
- System.IO.Compression cannot read AES entries. Tests open bundles with IronZIP.
Markdown

How do you plan and run a migration to IronZIP?

Rotate the chat input to Plan Mode with Shift+Tab before sending the next prompt. In Plan Mode, Agent can ask clarifying questions while it researches the code.

@src/ClientDrop/ @tests/ClientDrop.Tests/ @ironzip-bundles

Plan the move of BundleBuilder from System.IO.Compression to IronZIP.
Every bundle is encrypted with AES-256 using BundleOptions.Password.
Map each System.IO.Compression call to the IronZIP member that replaces it.
For each call, name the file it lives in.
Public method signatures on BundleBuilder stay as they are.
No test is renamed or loses an assertion.
Write no code yet.

In the plan, tell me how each of these works:
- The three files called statement.pdf in different folders all survive.
- The tests read an encrypted bundle.
- Reissue swaps a document without renaming it.
Text

The plan is a Markdown file you can edit, so a wrong mapping can be corrected before anything is built. When the plan is correct, build it from Plan Mode, or return to Agent mode with the next prompt, which adds the checks.

Build the approved plan with @ironzip-bundles attached.
Remove every System.IO.Compression call from src/ClientDrop.
In the tests, change only BundleReader.
Set CLIENTDROP_BUNDLE_PASSWORD to a throwaway value inside each command you run.

After the build, carry out these steps in sequence:
1. Build and run the tests.
2. Run "bundle C-1042", then run "inspect" on the result with that password.
3. Extract that bundle with IronZIP to an empty folder.

Report how many tests pass now and how many passed at the start.
Also report how many files the client folder and the extracted folder each hold.
Text

In our calibration, a straight translation that swapped each call for its nearest IronZIP member compiled cleanly and passed four of the six tests. The two failures were the extraction check and the reissue. The port that followed the rule passed all six.

How do you take one document out of a protected bundle?

BundleBuilder also needs a way to remove one document from a bundle a client has not downloaded yet. Highlight the whole Reissue method in BundleBuilder.cs, press Ctrl+Shift+L to add it to the open chat, and send the request in Agent mode.

Below the highlighted Reissue, add Withdraw(string bundlePath, string entryName).
It takes one document out of an existing bundle and keeps the rest encrypted.
For a name the bundle lacks, it throws KeyNotFoundException, as Reissue does.
Add a "withdraw <zip> <entry>" command to Program.cs.
Try it on a fresh C-1042 bundle, with CLIENTDROP_BUNDLE_PASSWORD set inside each command.
Show me what each command prints.
Text

The resulting Withdraw is a Contains guard, then Delete and Save, on an archive opened with its password. Withdrawing contract.pdf from C-1042 left six entries, all still encrypted. In our calibration a bundle of two documents kept one, and the constructor then failed to open the bundle.

Why does a one-document bundle reject its own password?

The IronZipArchive constructor rejects the correct password whenever a protected archive holds exactly one entry. In IronZIP 2026.10.2 it threw an Exception reading "Invalid Password!" for single-entry archives encrypted with AES-256, AES-128 and Traditional encryption, and the byte array overload and FromArchive did the same. ExtractArchiveToDirectory with the same password extracted the file with no error, and two entries or more opened normally.

Client C-1077 has a single document, a welcome letter. Mention its folder, the corrected letter and the program together.

@TestData/clients/C-1077/ @TestData/reissue/C-1077/ @src/ClientDrop/Program.cs

Client C-1077 has a single document.
Set the same throwaway CLIENTDROP_BUNDLE_PASSWORD inside each command.

Run these three steps in order:
1. Run bundle C-1077.
2. Run list on out/C-1077.zip.
3. Reissue its welcome-letter.pdf from TestData/reissue/C-1077/.

If any step throws, find the cause and fix it in BundleBuilder.
Don't catch and hide the exception.
If a line of @ironzip-bundles led to it, change that line too.
Then run all three steps again.
Show me the error you hit and the list output after the reissue.
Text

In our calibration the bundle was written, then the list and the reissue failed, and so did the bundle command itself, which lists the new bundle to print its entry count. Reading the bundle by extracting it into a temporary folder, and writing it again from that folder for a reissue or a withdrawal, listed the 2,643-byte letter and swapped in the corrected one. Append this block below the translations.

One-document bundles follow this rule:
- On a protected one-entry bundle, the IronZipArchive constructor rejects the correct password.
- List, reissue and withdraw such a bundle by extracting it with ExtractArchiveToDirectory.
- Then pack the extracted folder again.
Markdown

How do you write regression tests for the bundles?

A Cloud Agent can write the regression suite. It clones the repository from your connected source control, so push the port first, and add IRONZIP_LICENSE_KEY as a secret in the Cloud Agents dashboard before you start one.

@tests/ClientDrop.Tests/ @TestData/

Extend BundleBuilderTests for the IronZIP port with tests for these cases:
- The three statement.pdf documents from different C-1042 folders all survive a round trip.
- Those three documents keep distinct entry names.
- Every entry in the C-1042 bundle is encrypted.
- A wrong password fails when the bundle is extracted.
- A one-document bundle can be listed, reissued and extracted.
- Withdraw removes exactly one document.
- Withdraw throws KeyNotFoundException for an unknown name.

Compare extracted files by SHA-256, never archive bytes.
Run dotnet test and report how many tests pass and fail.
Text

The wrong password test has to extract the bundle. On a bundle of three entries, the constructor took a wrong password without an error, and the entry count, the entry list and the name lookup all answered as if it were right. ExtractArchiveToDirectory was the first call to refuse it, with ArgumentException "Invalid password!!". A port that lists entries by extracting therefore rejects a wrong password at the first read.

IronZIP's AI coding assistants guide runs one IronZIP task end to end against defined pass criteria.

What did the prompts produce in a real run?

The seven prompts were sent to Cursor in order, in one chat, against a copy of the ClientDrop repository made for this guide. The copy contained the System.IO.Compression BundleBuilder, six xUnit tests that read bundles with System.IO.Compression, and client C-1042. The rule file and client C-1077 were added immediately before the prompts that use them, and the license key was set only as an environment variable. Every figure below comes from builds and runs of the committed code after the chat ended.

  • All 6 tests passed before the port, and the same 6 passed after it.
  • The ported C-1042 bundle held 7 entries under unique flat names.
  • IronZIP extracted 7 files from that bundle, the same number as the client folder held.
  • pyzipper, a Python ZIP reader that shares no code with IronZIP, found AES-256 encryption on all 7 entries.
  • All 7 extracted files matched the files in the client folder by SHA-256.
  • Asked where IronZIP checks a password, Cursor named the constructor and cited the access example.
  • Withdraw threw KeyNotFoundException for a name the bundle lacked.
  • Before the fix, the bundle, list and reissue steps for C-1077 each threw Exception "Invalid Password!" from the IronZipArchive constructor.
  • After the fix, list showed welcome-letter.pdf at 2,643 bytes, and at 2,761 bytes after the reissue.
  • The reissued letter that pyzipper extracted matched the corrected file by SHA-256.
  • Each C-1077 bundle also held an empty entry named __bundle_keep, which extraction wrote out as a second file.
  • In the final code, withdrawing one document from a two-document bundle left one entry, and list then threw "Invalid Password!".
  • The test prompt added 6 tests, and all 12 passed.
  • IronZIP 2026.10.2 was the only package in the service, and no System.IO.Compression call remained in it.
  • Each Release build after a prompt finished without a warning or an error.
  • Some steps ran differently from the page. In Plan Mode, Cursor searched folders outside the repository for ironzip-bundles before it opened the rule file. For C-1077, Cursor added the __bundle_keep entry to one-document bundles and wrote that into the rule, in place of reading by extraction. The Cloud Agent prompt was sent locally in the same chat in Agent mode, not as a Cloud Agent.

Plan approval before any code also happens in the Claude Code guide, where the plan rebuilt each archive from an extracted copy and so handled a single-entry archive. The GitHub Copilot guide restricts its TAR rules to the log archiver and its tests through the applyTo value of a path-specific instructions file, and the globs restrict this rule the same way. The run record names the Cursor version and the model, and gives the total prompt time and the hardware of the test machine.


Troubleshooting


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.

Read More

Ready to Get Started?

Nuget Downloads 24,698Version:2026.10just released