# How to Use IronOCR with GitHub Copilot
.NET teams with established Visual Studio solutions for document capture, accounts payable, claims processing, or records management do not need to change editors to evaluate GitHub Copilot, as it supports their existing workflows.
Copilot runs in Visual Studio, VS Code, JetBrains IDEs, and on GitHub.com. IronOCR processes recognition locally in .NET.
For details on IronOCR's models for photographs and handwriting, refer to the [photo reading guide](https://ironsoftware.com/ocr/csharp/how-to/read-photo/) and the [handwriting guide](https://ironsoftware.com/ocr/csharp/how-to/read-handwritten-image/).
*as-heading:2(Quickstart)*
!!!--LIBRARY_NUGET_INSTALL_BLOCK--!!!
In your current IDE, state what the method must return and any default the model would otherwise have to recall.
```text
Add a ReadDeliveryNote method to Imports/DeliveryNotes.cs that uses IronOCR (the
IronOcr NuGet package, namespace IronOcr) to read a scanned delivery note and
return both its text and the barcode values found in the same pass. Barcode
reading is off by default, so switch it on before the read. Take the license key
from the IRONOCR_LICENSE_KEY environment variable, never inline. Then build and
fix any errors.
```
Set `IRONOCR_LICENSE_KEY` in the environment the editor starts from, and see the [license key guide](https://ironsoftware.com/ocr/csharp/get-started/license-keys/) for other places to keep the key. Without it, the first read stops at the license check, and Copilot cannot run the OCR code it writes.
<div class="hsg-featured-snippet">
<h3>Minimal Workflow (5 steps)</h3>
<ol>
<li><a class="js-modal-open" data-modal-id="trial-license-after-download" href="https://www.nuget.org/packages/IronOcr/">Download the C# OCR library from NuGet</a></li>
<li>Check your IronOCR conventions into <code>.github/copilot-instructions.md</code></li>
<li>Use inline chat for a single file and agent mode once several files are involved</li>
<li>Write a detailed issue when the cloud agent will work alone</li>
<li>Confirm each IronOCR member in the pull request using the <a href="https://ironsoftware.com/ocr/csharp/object-reference/api/">API reference</a></li>
</ol>
</div>
<br class="clear" />
---
## Where does Copilot fit into a project already in Visual Studio?
Use inline chat for a one-file IronOCR change. Switch to agent mode when the change spans several files, since it can build the project and run the OCR code itself. The cloud agent on GitHub takes an assigned issue and returns a pull request.
## How do you set IronOCR conventions for Copilot?
Commit the IronOCR conventions as `.github/copilot-instructions.md`, which Copilot Chat, agent mode and the cloud agent read. Inline completions ignore it.
```markdown
# Copilot instructions
## OCR
- Use IronOCR for all OCR work. The NuGet package is IronOcr on Windows and
IronOcr.Linux on Linux and Docker. The namespace is IronOcr. Do not add
another OCR engine or a cloud OCR service.
- Documentation: https://ironsoftware.com/ocr/csharp/llms.txt
Skill file: https://ironsoftware.com/ocr/csharp/skill.md
- Target the IronOcr version pinned in Directory.Packages.props. Do not upgrade
it as part of an unrelated change.
- Never inline a license key. Read it from configuration or the
IRONOCR_LICENSE_KEY environment variable.
- Always dispose OcrInput with a using block.
- Barcode reading is off by default. Set Configuration.ReadBarCodes only where needed.
- Apply only the image filters that fix a visible defect.
- Do not invent IronOCR API names. If a member is uncertain, say so and cite
the documentation rather than guessing.
## Testing
- Every OCR change must be run against pages with known values.
- Assert on extracted fields. Never assert on the full text of a page.
## Pull requests
- Say which IronOCR APIs the change introduces, and link the page for each.
- If the OCR tests fail, check the runner environment before changing code
that the issue did not ask you to touch.
```
## How do you give one folder its own OCR language rules?
IronOCR settings often vary by source, such as German supplier invoices and English warehouse scans. Put the German rules in `.github/instructions/ocr-german.instructions.md`. Copilot applies that file together with the repository-wide one whenever the file it is working on matches the path pattern at the top of the German file.
```markdown
---
applyTo: "Imports/De/**"
---
- Invoices in this folder are German. Set Language = OcrLanguage.German and add
English with AddSecondaryLanguage(OcrLanguage.English) for supplier names.
- German comes from the IronOcr.Languages.German NuGet package. Language packs
keep their own version numbers, so never align this one with IronOcr.
- Amounts use German formatting, such as 1.234,56. Parse them with the de-DE culture.
```
A German sample read with the newest German pack, 2020.11.2, and English as the secondary language returned "Gesamtbetrag: 3.271,07 EUR" at 96.6 confidence on that line.
## What makes an issue the cloud agent can act on?
An issue that only reports wrong invoice totals leaves the cloud agent to find the file at fault, the affected scans and the correct totals.
```markdown
Title: Totals misread on rotated scans from the warehouse scanner
**Files:** Imports/InvoiceReader.cs, Imports/ImportJob.cs
**IronOcr version:** as pinned in Directory.Packages.props
**Framework:** .NET 8
**Expected:** Every invoice in TestData/warehouse/ returns the total recorded in
TestData/warehouse/expected.csv, with line confidence of at least 80.
**Actual:** About a third of warehouse scans return totals with one wrong digit.
The pages are rotated a few degrees and have speckle. Invoices from the email
inbox read correctly. No exception is thrown.
**Constraints:** Keep the Total due parsing as it is. Do not change the public
signature of InvoiceReader.ReadTotal. No new packages.
**Acceptance:** Existing tests pass, plus a new test that reads every scan in
TestData/warehouse/ and matches expected.csv.
```
The note that emailed invoices read correctly directs the investigation to scan quality rather than parsing.
## Why do the cloud agent's tests fail on an IronOCR project?
By default, the cloud agent builds and tests on an ephemeral Ubuntu Linux runner. The `IronOcr` package ships only Windows native runtimes, so the runner needs `IronOcr.Linux`. A setup workflow at `.github/workflows/copilot-setup-steps.yml`, with its one job named `copilot-setup-steps`, closes that gap once it is merged into the default branch.
```text
Write .github/workflows/copilot-setup-steps.yml for this repository.
The job must be named copilot-setup-steps exactly, or it is ignored. Trigger it
manually, and on push and pull request limited to that one file path.
Run it on ubuntu-latest with read access to repository contents. Check out the
repository, set up the .NET SDK for the version this project targets, install
the native dependencies IronOCR needs on Ubuntu, then restore packages.
For those dependencies read
https://ironsoftware.com/ocr/csharp/get-started/linux/ and use what it lists for
Ubuntu rather than a list from memory. Note in a comment that the list can
change between releases.
The runner is Linux, so OCR there needs the IronOcr.Linux package this
repository's instructions name. Show me the finished YAML, then any project
change the runner still needs to restore IronOcr.Linux.
```
- **The license key:** The cloud agent cannot read Actions, Codespaces or Dependabot secrets, so the key needs an Agents secret. Add the key under Settings, then Secrets and variables, then Agents, with the same name the editor reads, and the agent receives it as an environment variable.
- **A failed setup step:** It does not stop the cloud agent. The agent skips the remaining steps and starts work anyway, so run the workflow once from the Actions tab and confirm it passes.
## What should you check before merging?
Review a Copilot pull request as you would a colleague's.
```text
/tests Add xUnit tests for this change: every scan in TestData/warehouse/ returns
the invoice number and total in its expected.csv, a page without a total returns
null rather than a guess, and reads below 80 confidence are flagged. Assert on
extracted fields, not on the full page text.
```
A new IronOCR release can change spacing and line breaks without changing the values. The [AI coding assistants guide](https://ironsoftware.com/ocr/csharp/ai-agents/ai/) turns this review into a repeatable test.
## How do you diagnose a wrong OCR result?
A wrong result usually has one of three causes. The page needs an [image filter](https://ironsoftware.com/ocr/csharp/how-to/image-quality-correction/) or a [higher DPI](https://ironsoftware.com/ocr/csharp/how-to/dpi-setting/), the document's language pack was never added, or the read targets the wrong [region](https://ironsoftware.com/ocr/csharp/how-to/ocr-region-of-an-image/). An empty barcode collection can also mean `Configuration.ReadBarCodes` was never set.
```text
Delivery notes in TestData/notes/ return their text, but about a third
come back with an empty barcode collection, while the same notes decode fine on
the handheld scanner.
Explain the cause before changing anything, then fix it in ReadDeliveryNote only.
Do not change the text extraction. Report how many notes return a barcode before
and after. Measure the current count first and base the explanation on what you
measured, not on a guess.
```
In a run without the measure-first instruction, Copilot initially blamed resolution, then traced the missing barcodes to QR codes printed in faded gray and recovered them by cropping a fixed region and selecting one shade of gray. In a second set with faded codes printed lower on the page, that fix read none of them. With the instruction, Copilot measured first, ruled out contrast, binarization, upscaling, and cropping, and added a second read after applying a sharpening filter. Always test fixes on pages Copilot has not previously seen.
If recognition works locally but fails on a runner or in a container, give Copilot the full exception message rather than a summary.
## What did the prompts produce in a real run?
Every prompt in this guide that runs in the editor was sent in sequence, over two chats, against a sample receiving app, a .NET 9 console project with central package management, an invoice reader and scans with known values. Each result below was measured again outside the chat.
- Delivery notes with a barcode went from 6 of 9 before the fix to 9 of 9 after it, and the same fix read 8 of 12 faded codes in the second set.
- The `/tests` suite passed 14 of 14. It also changed ImportJob's console output unasked, and it tested the confidence threshold on constructed records, not scans.
- After all four prompts the Release build was clean, with no hand edits.
- Two parts ran differently from the page. The person pasted the license key into the tests prompt, and Copilot kept it out of every file. The setup workflow, the cloud agent, its issue and the Agents secret need GitHub Actions or a GitHub repository, so none of them ran.
The assistant version, model, timings and test machine behind these numbers are listed with every other guide in the [run record](/ocr/csharp/ai-agents/ai/#the-run-record).
---
## Troubleshooting
- [Apply a License Key in IronOCR](https://ironsoftware.com/ocr/csharp/troubleshooting/apply-a-license-key-in-ironocr/) if a pull request builds but the first read throws a licensing exception
- [IronOCR on Linux](https://ironsoftware.com/ocr/csharp/get-started/linux/) if a Linux runner is missing native dependencies
- [Improve OCR Accuracy](https://ironsoftware.com/ocr/csharp/troubleshooting/improve-ocr-accuracy/) if extracted values differ from the scan
- [IronOCR Runtimes Folder](https://ironsoftware.com/ocr/csharp/troubleshooting/ironocr-runtimes-folder/) if native files are missing from the build output
---
## Questions?
If you have any questions, reach out to [support@ironsoftware.com](mailto:support@ironsoftware.com)
.NET teams with established Visual Studio solutions for document capture, accounts payable, claims processing, or records management do not need to change editors to evaluate GitHub Copilot, as it supports their existing workflows.
Copilot runs in Visual Studio, VS Code, JetBrains IDEs, and on GitHub.com. IronOCR processes recognition locally in .NET.
Install IronOCR by running the command above in the NuGet Package Manager Console, or search for the package in the NuGet Package Manager.
In your current IDE, state what the method must return and any default the model would otherwise have to recall.
Add a ReadDeliveryNote method to Imports/DeliveryNotes.cs that uses IronOCR (theIronOcr NuGet package, namespace IronOcr) to read a scanned delivery note andreturn both its text and the barcode values found in the same pass. Barcodereading is off by default, so switch it on before the read. Take the license keyfrom the IRONOCR_LICENSE_KEY environment variable, never inline. Then build andfix any errors.
Add a ReadDeliveryNote method to Imports/DeliveryNotes.cs that uses IronOCR (the
IronOcr NuGet package, namespace IronOcr) to read a scanned delivery note and
return both its text and the barcode values found in the same pass. Barcode
reading is off by default, so switch it on before the read. Take the license key
from the IRONOCR_LICENSE_KEY environment variable, never inline. Then build and
fix any errors.
Text
Set IRONOCR_LICENSE_KEY in the environment the editor starts from, and see the license key guide for other places to keep the key. Without it, the first read stops at the license check, and Copilot cannot run the OCR code it writes.
Check your IronOCR conventions into .github/copilot-instructions.md
Use inline chat for a single file and agent mode once several files are involved
Write a detailed issue when the cloud agent will work alone
Confirm each IronOCR member in the pull request using the API reference
Where does Copilot fit into a project already in Visual Studio?
Use inline chat for a one-file IronOCR change. Switch to agent mode when the change spans several files, since it can build the project and run the OCR code itself. The cloud agent on GitHub takes an assigned issue and returns a pull request.
How do you set IronOCR conventions for Copilot?
Commit the IronOCR conventions as .github/copilot-instructions.md, which Copilot Chat, agent mode and the cloud agent read. Inline completions ignore it.
# Copilot instructions## OCR- Use IronOCR for all OCR work. The NuGet package is IronOcr on Windows and IronOcr.Linux on Linux and Docker. The namespace is IronOcr. Do not add another OCR engine or a cloud OCR service.- Documentation: https://ironsoftware.com/ocr/csharp/llms.txt Skill file: https://ironsoftware.com/ocr/csharp/skill.md- Target the IronOcr version pinned in Directory.Packages.props. Do not upgrade it as part of an unrelated change.- Never inline a license key. Read it from configuration or the IRONOCR_LICENSE_KEY environment variable.- Always dispose OcrInput with a using block.- Barcode reading is off by default. Set Configuration.ReadBarCodes only where needed.- Apply only the image filters that fix a visible defect.- Do not invent IronOCR API names. If a member is uncertain, say so and cite the documentation rather than guessing.## Testing- Every OCR change must be run against pages with known values.- Assert on extracted fields. Never assert on the full text of a page.## Pull requests- Say which IronOCR APIs the change introduces, and link the page for each.- If the OCR tests fail, check the runner environment before changing code that the issue did not ask you to touch.
# Copilot instructions
## OCR
- Use IronOCR for all OCR work. The NuGet package is IronOcr on Windows and
IronOcr.Linux on Linux and Docker. The namespace is IronOcr. Do not add
another OCR engine or a cloud OCR service.
- Documentation: https://ironsoftware.com/ocr/csharp/llms.txt
Skill file: https://ironsoftware.com/ocr/csharp/skill.md
- Target the IronOcr version pinned in Directory.Packages.props. Do not upgrade
it as part of an unrelated change.
- Never inline a license key. Read it from configuration or the
IRONOCR_LICENSE_KEY environment variable.
- Always dispose OcrInput with a using block.
- Barcode reading is off by default. Set Configuration.ReadBarCodes only where needed.
- Apply only the image filters that fix a visible defect.
- Do not invent IronOCR API names. If a member is uncertain, say so and cite
the documentation rather than guessing.
## Testing
- Every OCR change must be run against pages with known values.
- Assert on extracted fields. Never assert on the full text of a page.
## Pull requests
- Say which IronOCR APIs the change introduces, and link the page for each.
- If the OCR tests fail, check the runner environment before changing code
that the issue did not ask you to touch.
Text
How do you give one folder its own OCR language rules?
IronOCR settings often vary by source, such as German supplier invoices and English warehouse scans. Put the German rules in .github/instructions/ocr-german.instructions.md. Copilot applies that file together with the repository-wide one whenever the file it is working on matches the path pattern at the top of the German file.
---applyTo: "Imports/De/**"---- Invoices in this folder are German. Set Language = OcrLanguage.German and add English with AddSecondaryLanguage(OcrLanguage.English) for supplier names.- German comes from the IronOcr.Languages.German NuGet package. Language packs keep their own version numbers, so never align this one with IronOcr.- Amounts use German formatting, such as 1.234,56. Parse them with the de-DE culture.
---
applyTo: "Imports/De/**"
---
- Invoices in this folder are German. Set Language = OcrLanguage.German and add
English with AddSecondaryLanguage(OcrLanguage.English) for supplier names.
- German comes from the IronOcr.Languages.German NuGet package. Language packs
keep their own version numbers, so never align this one with IronOcr.
- Amounts use German formatting, such as 1.234,56. Parse them with the de-DE culture.
Text
A German sample read with the newest German pack, 2020.11.2, and English as the secondary language returned "Gesamtbetrag: 3.271,07 EUR" at 96.6 confidence on that line.
What makes an issue the cloud agent can act on?
An issue that only reports wrong invoice totals leaves the cloud agent to find the file at fault, the affected scans and the correct totals.
Title: Totals misread on rotated scans from the warehouse scanner**Files:** Imports/InvoiceReader.cs, Imports/ImportJob.cs**IronOcr version:** as pinned in Directory.Packages.props**Framework:** .NET 8**Expected:** Every invoice in TestData/warehouse/ returns the total recorded inTestData/warehouse/expected.csv, with line confidence of at least 80.**Actual:** About a third of warehouse scans return totals with one wrong digit.The pages are rotated a few degrees and have speckle. Invoices from the emailinbox read correctly. No exception is thrown.**Constraints:** Keep the Total due parsing as it is. Do not change the publicsignature of InvoiceReader.ReadTotal. No new packages.**Acceptance:** Existing tests pass, plus a new test that reads every scan inTestData/warehouse/ and matches expected.csv.
Title: Totals misread on rotated scans from the warehouse scanner
**Files:** Imports/InvoiceReader.cs, Imports/ImportJob.cs
**IronOcr version:** as pinned in Directory.Packages.props
**Framework:** .NET 8
**Expected:** Every invoice in TestData/warehouse/ returns the total recorded in
TestData/warehouse/expected.csv, with line confidence of at least 80.
**Actual:** About a third of warehouse scans return totals with one wrong digit.
The pages are rotated a few degrees and have speckle. Invoices from the email
inbox read correctly. No exception is thrown.
**Constraints:** Keep the Total due parsing as it is. Do not change the public
signature of InvoiceReader.ReadTotal. No new packages.
**Acceptance:** Existing tests pass, plus a new test that reads every scan in
TestData/warehouse/ and matches expected.csv.
Text
The note that emailed invoices read correctly directs the investigation to scan quality rather than parsing.
Why do the cloud agent's tests fail on an IronOCR project?
By default, the cloud agent builds and tests on an ephemeral Ubuntu Linux runner. The IronOcr package ships only Windows native runtimes, so the runner needs IronOcr.Linux. A setup workflow at .github/workflows/copilot-setup-steps.yml, with its one job named copilot-setup-steps, closes that gap once it is merged into the default branch.
Write .github/workflows/copilot-setup-steps.yml for this repository.The job must be named copilot-setup-steps exactly, or it is ignored. Trigger itmanually, and on push and pull request limited to that one file path.Run it on ubuntu-latest with read access to repository contents. Check out therepository, set up the .NET SDK for the version this project targets, installthe native dependencies IronOCR needs on Ubuntu, then restore packages.For those dependencies readhttps://ironsoftware.com/ocr/csharp/get-started/linux/ and use what it lists forUbuntu rather than a list from memory. Note in a comment that the list canchange between releases.The runner is Linux, so OCR there needs the IronOcr.Linux package thisrepository's instructions name. Show me the finished YAML, then any projectchange the runner still needs to restore IronOcr.Linux.
Write .github/workflows/copilot-setup-steps.yml for this repository.
The job must be named copilot-setup-steps exactly, or it is ignored. Trigger it
manually, and on push and pull request limited to that one file path.
Run it on ubuntu-latest with read access to repository contents. Check out the
repository, set up the .NET SDK for the version this project targets, install
the native dependencies IronOCR needs on Ubuntu, then restore packages.
For those dependencies read
https://ironsoftware.com/ocr/csharp/get-started/linux/ and use what it lists for
Ubuntu rather than a list from memory. Note in a comment that the list can
change between releases.
The runner is Linux, so OCR there needs the IronOcr.Linux package this
repository's instructions name. Show me the finished YAML, then any project
change the runner still needs to restore IronOcr.Linux.
Text
The license key: The cloud agent cannot read Actions, Codespaces or Dependabot secrets, so the key needs an Agents secret. Add the key under Settings, then Secrets and variables, then Agents, with the same name the editor reads, and the agent receives it as an environment variable.
A failed setup step: It does not stop the cloud agent. The agent skips the remaining steps and starts work anyway, so run the workflow once from the Actions tab and confirm it passes.
What should you check before merging?
Review a Copilot pull request as you would a colleague's.
/tests Add xUnit tests for this change: every scan in TestData/warehouse/ returnsthe invoice number and total in its expected.csv, a page without a total returnsnull rather than a guess, and reads below 80 confidence are flagged. Assert onextracted fields, not on the full page text.
/tests Add xUnit tests for this change: every scan in TestData/warehouse/ returns
the invoice number and total in its expected.csv, a page without a total returns
null rather than a guess, and reads below 80 confidence are flagged. Assert on
extracted fields, not on the full page text.
Text
A new IronOCR release can change spacing and line breaks without changing the values. The AI coding assistants guide turns this review into a repeatable test.
How do you diagnose a wrong OCR result?
A wrong result usually has one of three causes. The page needs an image filter or a higher DPI, the document's language pack was never added, or the read targets the wrong region. An empty barcode collection can also mean Configuration.ReadBarCodes was never set.
Delivery notes in TestData/notes/ return their text, but about a thirdcome back with an empty barcode collection, while the same notes decode fine onthe handheld scanner.Explain the cause before changing anything, then fix it in ReadDeliveryNote only.Do not change the text extraction. Report how many notes return a barcode beforeand after. Measure the current count first and base the explanation on what youmeasured, not on a guess.
Delivery notes in TestData/notes/ return their text, but about a third
come back with an empty barcode collection, while the same notes decode fine on
the handheld scanner.
Explain the cause before changing anything, then fix it in ReadDeliveryNote only.
Do not change the text extraction. Report how many notes return a barcode before
and after. Measure the current count first and base the explanation on what you
measured, not on a guess.
Text
In a run without the measure-first instruction, Copilot initially blamed resolution, then traced the missing barcodes to QR codes printed in faded gray and recovered them by cropping a fixed region and selecting one shade of gray. In a second set with faded codes printed lower on the page, that fix read none of them. With the instruction, Copilot measured first, ruled out contrast, binarization, upscaling, and cropping, and added a second read after applying a sharpening filter. Always test fixes on pages Copilot has not previously seen.
If recognition works locally but fails on a runner or in a container, give Copilot the full exception message rather than a summary.
What did the prompts produce in a real run?
Every prompt in this guide that runs in the editor was sent in sequence, over two chats, against a sample receiving app, a .NET 9 console project with central package management, an invoice reader and scans with known values. Each result below was measured again outside the chat.
Delivery notes with a barcode went from 6 of 9 before the fix to 9 of 9 after it, and the same fix read 8 of 12 faded codes in the second set.
The /tests suite passed 14 of 14. It also changed ImportJob's console output unasked, and it tested the confidence threshold on constructed records, not scans.
After all four prompts the Release build was clean, with no hand edits.
Two parts ran differently from the page. The person pasted the license key into the tests prompt, and Copilot kept it out of every file. The setup workflow, the cloud agent, its issue and the Agents secret need GitHub Actions or a GitHub repository, so none of them ran.
The assistant version, model, timings and test machine behind these numbers are listed with every other guide in the run record.
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.