From 41933e17f71bf89f5f8a8537f5e3fc99b6cb10f2 Mon Sep 17 00:00:00 2001
From: sebastianMindee <130448732+sebastianMindee@users.noreply.github.com>
Date: Tue, 21 Apr 2026 17:27:03 +0200
Subject: [PATCH 1/3] :sparkles: add nuGet support for CLI
---
.github/workflows/_publish-cli-code.yml | 49 +++++++++++++++++++++++++
.github/workflows/publish-release.yml | 3 ++
src/Mindee.Cli/Mindee.Cli.csproj | 3 ++
3 files changed, 55 insertions(+)
create mode 100644 .github/workflows/_publish-cli-code.yml
diff --git a/.github/workflows/_publish-cli-code.yml b/.github/workflows/_publish-cli-code.yml
new file mode 100644
index 000000000..bc38c5476
--- /dev/null
+++ b/.github/workflows/_publish-cli-code.yml
@@ -0,0 +1,49 @@
+name: Publish CLI to NuGet
+
+on:
+ workflow_call:
+ workflow_dispatch:
+
+jobs:
+ publish:
+ name: Publish CLI release to NuGet
+ runs-on: ubuntu-latest
+
+ steps:
+ - name: Check out Git repository
+ uses: actions/checkout@v5
+
+ - name: Setup .NET
+ uses: actions/setup-dotnet@v4
+ with:
+ dotnet-version: '10.0.x'
+
+ - name: Restore strong-name key from secret
+ run: |
+ echo "${{ secrets.MINDEE_SNK_B64 }}" | base64 -d > /tmp/Mindee.snk
+ chmod 600 /tmp/Mindee.snk
+
+ - name: Install dependencies
+ run: dotnet restore "src/Mindee.Cli" -p:TargetFrameworks=net8.0
+
+ - name: Build (strong-name signed)
+ run: dotnet build "src/Mindee.Cli" --configuration Release --no-restore -p:TargetFrameworks=net8.0 -p:MindeeStrongNameKeyFile=/tmp/Mindee.snk
+
+ - name: Pack
+ run: dotnet pack "src/Mindee.Cli" -c Release -p:PackAsTool=true -p:TargetFrameworks=net8.0 -p:IncludeSymbols=true -p:SymbolPackageFormat=snupkg --no-build --no-restore --output nuget
+
+ - name: Verify strong-name (PublicKeyToken)
+ run: |
+ sudo apt-get update
+ sudo apt-get install -y mono-devel unzip
+ DLL_PATH=$(unzip -Z -1 nuget/*.nupkg | grep -m1 '/Mindee.dll$')
+ if [ -z "$DLL_PATH" ]; then
+ echo "Mindee.dll not found in packaged CLI tool."
+ exit 1
+ fi
+ unzip -p nuget/*.nupkg "$DLL_PATH" > /tmp/Mindee.dll
+ sn -T /tmp/Mindee.dll
+ sn -vf /tmp/Mindee.dll
+
+ - name: Publish NuGet packages to NuGet
+ run: dotnet nuget push nuget/*.nupkg --api-key ${{ secrets.NUGET_KEY }} --source "nuget.org" --skip-duplicate
diff --git a/.github/workflows/publish-release.yml b/.github/workflows/publish-release.yml
index 5a369a4f3..0053387db 100644
--- a/.github/workflows/publish-release.yml
+++ b/.github/workflows/publish-release.yml
@@ -15,3 +15,6 @@ jobs:
publish_code:
uses: mindee/mindee-api-dotnet/.github/workflows/_publish-code.yml@main
secrets: inherit
+ publish_cli_code:
+ uses: mindee/mindee-api-dotnet/.github/workflows/_publish-cli-code.yml@main
+ secrets: inherit
diff --git a/src/Mindee.Cli/Mindee.Cli.csproj b/src/Mindee.Cli/Mindee.Cli.csproj
index 9c1119201..fc70dbdf4 100644
--- a/src/Mindee.Cli/Mindee.Cli.csproj
+++ b/src/Mindee.Cli/Mindee.Cli.csproj
@@ -4,6 +4,8 @@
Exe
enable
enable
+ true
+ mindee
@@ -43,6 +45,7 @@
+
From 056ff2088ee4397a555ed98cd92550a8bc0bfaee Mon Sep 17 00:00:00 2001
From: sebastianMindee <130448732+sebastianMindee@users.noreply.github.com>
Date: Tue, 21 Apr 2026 17:44:11 +0200
Subject: [PATCH 2/3] fix thresholds for test
---
tests/Mindee.IntegrationTests/V2/FileOperations/CropTest.cs | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/tests/Mindee.IntegrationTests/V2/FileOperations/CropTest.cs b/tests/Mindee.IntegrationTests/V2/FileOperations/CropTest.cs
index e851e459e..70778c0a1 100644
--- a/tests/Mindee.IntegrationTests/V2/FileOperations/CropTest.cs
+++ b/tests/Mindee.IntegrationTests/V2/FileOperations/CropTest.cs
@@ -80,10 +80,10 @@ public async Task Extract_Crops_From_Image_Correctly()
extractedImages.SaveAllToDisk(_outputDir, 50);
var file1Info = new FileInfo(Path.Combine(_outputDir, "crop_001.jpg"));
- Assert.InRange(file1Info.Length, 99000, 110000);
+ Assert.InRange(file1Info.Length, 98000, 110000);
var file2Info = new FileInfo(Path.Combine(_outputDir, "crop_002.jpg"));
- Assert.InRange(file2Info.Length, 99000, 110000);
+ Assert.InRange(file2Info.Length, 98000, 110000);
}
[Fact(Timeout = 180000)]
From dcb79f09bacfd3322e0fcbd21b356a8d716635e6 Mon Sep 17 00:00:00 2001
From: sebastianMindee <130448732+sebastianMindee@users.noreply.github.com>
Date: Wed, 22 Apr 2026 13:08:14 +0200
Subject: [PATCH 3/3] fix CLI for nuget publish
---
.gitignore | 2 +
src/Mindee.Cli/Commands/V1/PredictCommand.cs | 15 ++-
.../Commands/V2/InferenceCommand.cs | 45 ++++++-
.../Commands/V2/SearchModelsCommand.cs | 46 ++++++-
src/Mindee.Cli/Mindee.Cli.csproj | 2 +-
src/Mindee.Cli/Program.cs | 94 +++++---------
src/Mindee.Cli/README.md | 116 ++++++++++++++++++
7 files changed, 251 insertions(+), 69 deletions(-)
create mode 100644 src/Mindee.Cli/README.md
diff --git a/.gitignore b/.gitignore
index d1cbd4e00..30a04578b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -370,3 +370,5 @@ _site
# StrongName files
*.snk
*.snk.b64
+# Local CLI publish.
+dotnet-tools.json
diff --git a/src/Mindee.Cli/Commands/V1/PredictCommand.cs b/src/Mindee.Cli/Commands/V1/PredictCommand.cs
index 790b5831a..b1e7bddb9 100644
--- a/src/Mindee.Cli/Commands/V1/PredictCommand.cs
+++ b/src/Mindee.Cli/Commands/V1/PredictCommand.cs
@@ -1,5 +1,6 @@
using System.CommandLine;
using System.Text.Json;
+using Microsoft.Extensions.Options;
using Mindee.Input;
using Mindee.V1;
using Mindee.V1.ClientOptions;
@@ -93,7 +94,7 @@ public PredictCommand(CommandOptions options)
Arguments.Add(_pathArgument);
}
- public void ConfigureAction(V1Client mindeeClientV1)
+ public void ConfigureAction(Func clientFactory)
{
this.SetAction(parseResult =>
{
@@ -102,6 +103,18 @@ public void ConfigureAction(V1Client mindeeClientV1)
var fullText = _fullTextOption != null && parseResult.GetValue(_fullTextOption);
var output = parseResult.GetValue(_outputOption);
var isAsync = _asyncOption != null && parseResult.GetValue(_asyncOption);
+ V1Client mindeeClientV1;
+ try
+ {
+ mindeeClientV1 = clientFactory();
+ }
+ catch (OptionsValidationException)
+ {
+ Console.Error.WriteLine(
+ "The Mindee V1 API key is missing. " +
+ "Please provide it via the '--api-key' option or your configured environment variable.");
+ return 1;
+ }
var handler = new Handler(mindeeClientV1);
return handler.InvokeAsync(path, allWords, fullText, output, isAsync).GetAwaiter().GetResult();
diff --git a/src/Mindee.Cli/Commands/V2/InferenceCommand.cs b/src/Mindee.Cli/Commands/V2/InferenceCommand.cs
index cfb2901b0..f86099097 100644
--- a/src/Mindee.Cli/Commands/V2/InferenceCommand.cs
+++ b/src/Mindee.Cli/Commands/V2/InferenceCommand.cs
@@ -1,5 +1,7 @@
using System.CommandLine;
using System.Text.Json;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Options;
using Mindee.Input;
using Mindee.V2.Parsing;
using Mindee.V2.Product.Classification;
@@ -12,6 +14,7 @@
using Mindee.V2.Product.Ocr.Params;
using Mindee.V2.Product.Split;
using Mindee.V2.Product.Split.Params;
+using SettingsV2 = Mindee.V2.Http.Settings;
using V2Client = Mindee.V2.Client;
namespace Mindee.Cli.Commands.V2
@@ -71,6 +74,7 @@ class InferenceCommand : Command
private readonly Option? _textContextOption;
private readonly Option _modelIdOption;
private readonly Argument _pathArgument;
+ private readonly Option _apiKeyOption;
public InferenceCommand(InferenceCommandOptions options)
: base(options.Name, options.Description)
@@ -78,8 +82,8 @@ public InferenceCommand(InferenceCommandOptions options)
_modelIdOption =
new Option("--model-id", "-m") { Description = "ID of the model to use", Required = true };
Options.Add(_modelIdOption);
- var apiKeyOption = new Option("--api-key", "-k") { Description = "Mindee V2 API key." };
- Options.Add(apiKeyOption); // Will not be used at this step, only here for help display purposes.
+ _apiKeyOption = new Option("--api-key", "-k") { Description = "Mindee V2 API key." };
+ Options.Add(_apiKeyOption);
_productName = options.Name;
_aliasOption = new Option("--alias", "-a")
@@ -157,8 +161,28 @@ public InferenceCommand(InferenceCommandOptions options)
Arguments.Add(_pathArgument);
}
- public void ConfigureAction(V2Client mindeeClientV2)
+ public void ConfigureAction(IServiceProvider services)
{
+ Validators.Add(commandResult =>
+ {
+ var apiKey = commandResult.GetValue(_apiKeyOption);
+ if (!string.IsNullOrWhiteSpace(apiKey))
+ {
+ return;
+ }
+
+ try
+ {
+ _ = services.GetRequiredService>().Value;
+ }
+ catch (OptionsValidationException)
+ {
+ commandResult.AddError(
+ "The Mindee V2 API key is missing. " +
+ "Please provide it via the '--api-key' option or your configured environment variable.");
+ }
+ });
+
this.SetAction(parseResult =>
{
var path = parseResult.GetValue(_pathArgument)!;
@@ -180,6 +204,21 @@ public void ConfigureAction(V2Client mindeeClientV2)
}
var output = parseResult.GetValue(_outputOption);
+ var apiKey = parseResult.GetValue(_apiKeyOption);
+ V2Client mindeeClientV2;
+ try
+ {
+ mindeeClientV2 = !string.IsNullOrWhiteSpace(apiKey)
+ ? new V2Client(apiKey)
+ : services.GetRequiredService();
+ }
+ catch (OptionsValidationException)
+ {
+ Console.Error.WriteLine(
+ "The Mindee V2 API key is missing. " +
+ "Please provide it via the '--api-key' option or your configured environment variable.");
+ return 1;
+ }
var handler = new Handler(mindeeClientV2);
return handler
diff --git a/src/Mindee.Cli/Commands/V2/SearchModelsCommand.cs b/src/Mindee.Cli/Commands/V2/SearchModelsCommand.cs
index d49304d57..63a7bac12 100644
--- a/src/Mindee.Cli/Commands/V2/SearchModelsCommand.cs
+++ b/src/Mindee.Cli/Commands/V2/SearchModelsCommand.cs
@@ -1,6 +1,9 @@
using System.CommandLine;
using System.Text.Json;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Options;
using Mindee.V2.Parsing.Search;
+using SettingsV2 = Mindee.V2.Http.Settings;
using V2Client = Mindee.V2.Client;
namespace Mindee.Cli.Commands.V2
@@ -10,6 +13,7 @@ namespace Mindee.Cli.Commands.V2
///
public class SearchModelsCommand : Command
{
+ private readonly Option _apiKeyOption;
private readonly Option? _nameOption;
private readonly Option? _modelTypeOption;
private readonly Option? _rawOption;
@@ -19,6 +23,9 @@ public class SearchModelsCommand : Command
///
public SearchModelsCommand() : base("search-models", "Search available models.")
{
+ _apiKeyOption = new Option("--api-key", "-k") { Description = "Mindee V2 API key." };
+ Options.Add(_apiKeyOption);
+
_nameOption = new Option("--name", "-n")
{
Description = "Filter by model name partial match (case insensitive).",
@@ -50,14 +57,49 @@ Filter by exact model type (case sensitive).
///
///
///
- /// V2 Client instance
- public void ConfigureAction(V2Client mindeeClientV2)
+ /// Service provider for dependency resolution
+ public void ConfigureAction(IServiceProvider services)
{
+ Validators.Add(commandResult =>
+ {
+ var apiKey = commandResult.GetValue(_apiKeyOption);
+ if (!string.IsNullOrWhiteSpace(apiKey))
+ {
+ return;
+ }
+
+ try
+ {
+ _ = services.GetRequiredService>().Value;
+ }
+ catch (OptionsValidationException)
+ {
+ commandResult.AddError(
+ "The Mindee V2 API key is missing. " +
+ "Please provide it via the '--api-key' option or your configured environment variable.");
+ }
+ });
+
this.SetAction(parseResult =>
{
var name = _nameOption != null ? parseResult.GetValue(_nameOption) : null;
var modelType = _modelTypeOption != null ? parseResult.GetValue(_modelTypeOption) : null;
var raw = _rawOption != null && parseResult.GetValue(_rawOption);
+ var apiKey = parseResult.GetValue(_apiKeyOption);
+ V2Client mindeeClientV2;
+ try
+ {
+ mindeeClientV2 = !string.IsNullOrWhiteSpace(apiKey)
+ ? new V2Client(apiKey)
+ : services.GetRequiredService();
+ }
+ catch (OptionsValidationException)
+ {
+ Console.Error.WriteLine(
+ "The Mindee V2 API key is missing. " +
+ "Please provide it via the '--api-key' option or your configured environment variable.");
+ return 1;
+ }
var handler = new Handler(mindeeClientV2);
return handler
diff --git a/src/Mindee.Cli/Mindee.Cli.csproj b/src/Mindee.Cli/Mindee.Cli.csproj
index fc70dbdf4..f2fe4833e 100644
--- a/src/Mindee.Cli/Mindee.Cli.csproj
+++ b/src/Mindee.Cli/Mindee.Cli.csproj
@@ -45,7 +45,7 @@
-
+
diff --git a/src/Mindee.Cli/Program.cs b/src/Mindee.Cli/Program.cs
index 359ab3764..8108d1ca7 100644
--- a/src/Mindee.Cli/Program.cs
+++ b/src/Mindee.Cli/Program.cs
@@ -82,9 +82,7 @@
Mindee.V1.Product.Receipt.ReceiptV5Document
>;
using SettingsV1 = Mindee.V1.Http.Settings;
-using SettingsV2 = Mindee.V2.Http.Settings;
using V1Client = Mindee.V1.Client;
-using V2Client = Mindee.V2.Client;
var host = Host.CreateDefaultBuilder(args)
.ConfigureLogging((_, logging) =>
@@ -109,6 +107,12 @@ static void BuildV1Commands(Command v1Command, IServiceProvider services, string
var apiKeyOption = new Option("--api-key", "-k") { Description = "Mindee V1 API key." };
v1Command.Validators.Add(commandResult =>
{
+ var apiKey = commandResult.GetValue(apiKeyOption);
+ if (!string.IsNullOrWhiteSpace(apiKey))
+ {
+ return;
+ }
+
try
{
_ = services.GetRequiredService>().Value;
@@ -123,138 +127,104 @@ static void BuildV1Commands(Command v1Command, IServiceProvider services, string
v1Command.Add(apiKeyOption);
var parseResult = v1Command.Parse(args);
var apiKey = parseResult.GetValue(apiKeyOption);
- V1Client mindeeV1Client;
-
- if (apiKey != null)
- {
- mindeeV1Client = new V1Client(apiKey);
- }
- else
- {
- mindeeV1Client = services.GetRequiredService();
- }
+ Func mindeeV1ClientFactory = !string.IsNullOrWhiteSpace(apiKey)
+ ? () => new V1Client(apiKey)
+ : services.GetRequiredService;
var barcodeReaderCmd = new PredictBarcodeReaderCommand(new CommandOptions(
"barcode-reader", "Barcode Reader",
false, false, true, false));
- barcodeReaderCmd.ConfigureAction(mindeeV1Client);
+ barcodeReaderCmd.ConfigureAction(mindeeV1ClientFactory);
v1Command.Subcommands.Add(barcodeReaderCmd);
var cropperCmd = new PredictCropperCommand(new CommandOptions(
"cropper", "Cropper",
false, false, true, false));
- cropperCmd.ConfigureAction(mindeeV1Client);
+ cropperCmd.ConfigureAction(mindeeV1ClientFactory);
v1Command.Subcommands.Add(cropperCmd);
var financialDocumentCmd = new PredictFinancialDocumentCommand(new CommandOptions(
"financial-document", "Financial Document",
true, false, true, true));
- financialDocumentCmd.ConfigureAction(mindeeV1Client);
+ financialDocumentCmd.ConfigureAction(mindeeV1ClientFactory);
v1Command.Subcommands.Add(financialDocumentCmd);
var bankAccountDetailsCmd = new PredictBankAccountDetailsCommand(new CommandOptions(
"fr-bank-account-details", "FR Bank Account Details",
false, false, true, false));
- bankAccountDetailsCmd.ConfigureAction(mindeeV1Client);
+ bankAccountDetailsCmd.ConfigureAction(mindeeV1ClientFactory);
v1Command.Subcommands.Add(bankAccountDetailsCmd);
var carteGriseCmd = new PredictCarteGriseCommand(new CommandOptions(
"fr-carte-grise", "FR Carte Grise",
false, false, true, false));
- carteGriseCmd.ConfigureAction(mindeeV1Client);
+ carteGriseCmd.ConfigureAction(mindeeV1ClientFactory);
v1Command.Subcommands.Add(carteGriseCmd);
var healthCardCmd = new PredictHealthCardCommand(new CommandOptions(
"fr-health-card", "FR Health Card",
false, false, false, true));
- healthCardCmd.ConfigureAction(mindeeV1Client);
+ healthCardCmd.ConfigureAction(mindeeV1ClientFactory);
v1Command.Subcommands.Add(healthCardCmd);
var idCardCmd = new PredictIdCardCommand(new CommandOptions(
"fr-carte-nationale-d-identite", "FR Carte Nationale d'Identité",
false, false, true, false));
- idCardCmd.ConfigureAction(mindeeV1Client);
+ idCardCmd.ConfigureAction(mindeeV1ClientFactory);
v1Command.Subcommands.Add(idCardCmd);
var payslipCmd = new PredictPayslipCommand(new CommandOptions(
"fr-payslip", "FR Payslip",
false, false, false, true));
- payslipCmd.ConfigureAction(mindeeV1Client);
+ payslipCmd.ConfigureAction(mindeeV1ClientFactory);
v1Command.Subcommands.Add(payslipCmd);
var internationalIdCmd = new PredictInternationalIdCommand(new CommandOptions(
"international-id", "International ID",
false, true, false, true));
- internationalIdCmd.ConfigureAction(mindeeV1Client);
+ internationalIdCmd.ConfigureAction(mindeeV1ClientFactory);
v1Command.Subcommands.Add(internationalIdCmd);
var invoiceCmd = new PredictInvoiceCommand(new CommandOptions(
"invoice", "Invoice",
true, false, true, true));
- invoiceCmd.ConfigureAction(mindeeV1Client);
+ invoiceCmd.ConfigureAction(mindeeV1ClientFactory);
v1Command.Subcommands.Add(invoiceCmd);
var invoiceSplitterCmd = new PredictInvoiceSplitterCommand(new CommandOptions(
"invoice-splitter", "Invoice Splitter",
false, false, false, true));
- invoiceSplitterCmd.ConfigureAction(mindeeV1Client);
+ invoiceSplitterCmd.ConfigureAction(mindeeV1ClientFactory);
v1Command.Subcommands.Add(invoiceSplitterCmd);
var multiReceiptsDetectorCmd = new PredictMultiReceiptsDetectorCommand(new CommandOptions(
"multi-receipts-detector", "Multi Receipts Detector",
false, false, true, false));
- multiReceiptsDetectorCmd.ConfigureAction(mindeeV1Client);
+ multiReceiptsDetectorCmd.ConfigureAction(mindeeV1ClientFactory);
v1Command.Subcommands.Add(multiReceiptsDetectorCmd);
var passportCmd = new PredictPassportCommand(new CommandOptions(
"passport", "Passport",
false, false, true, false));
- passportCmd.ConfigureAction(mindeeV1Client);
+ passportCmd.ConfigureAction(mindeeV1ClientFactory);
v1Command.Subcommands.Add(passportCmd);
var receiptCmd = new PredictReceiptCommand(new CommandOptions(
"receipt", "Receipt",
true, false, true, true));
- receiptCmd.ConfigureAction(mindeeV1Client);
+ receiptCmd.ConfigureAction(mindeeV1ClientFactory);
v1Command.Subcommands.Add(receiptCmd);
var bankCheckCmd = new PredictBankCheckCommand(new CommandOptions(
"us-bank-check", "US Bank Check",
false, false, true, false));
- bankCheckCmd.ConfigureAction(mindeeV1Client);
+ bankCheckCmd.ConfigureAction(mindeeV1ClientFactory);
v1Command.Subcommands.Add(bankCheckCmd);
}
-static void BuildV2Commands(Command v2Command, IServiceProvider services, string[] args)
+static void BuildV2Commands(Command v2Command, IServiceProvider services)
{
- var apiKeyOption = new Option("--api-key", "-k") { Description = "Mindee V2 API key." };
- v2Command.Validators.Add(commandResult =>
- {
- try
- {
- _ = services.GetRequiredService>().Value;
- }
- catch (OptionsValidationException)
- {
- commandResult.AddError(
- "The Mindee V2 API key is missing. " +
- "Please provide it via the '--api-key' option or your configured environment variable.");
- }
- });
- v2Command.Add(apiKeyOption);
- var parseResult = v2Command.Parse(args);
- var apiKey = parseResult.GetValue(apiKeyOption);
- V2Client mindeeV2Client;
-
- if (apiKey != null)
- {
- mindeeV2Client = new V2Client(apiKey);
- }
- else
- {
- mindeeV2Client = services.GetRequiredService();
- }
var searchModelsCmd = new SearchModelsCommand();
- searchModelsCmd.ConfigureAction(mindeeV2Client);
+ searchModelsCmd.ConfigureAction(services);
v2Command.Add(searchModelsCmd);
var classificationCmd = new InferenceCommand(
new InferenceCommandOptions(
@@ -266,7 +236,7 @@ static void BuildV2Commands(Command v2Command, IServiceProvider services, string
false,
false));
v2Command.Subcommands.Add(classificationCmd);
- classificationCmd.ConfigureAction(mindeeV2Client);
+ classificationCmd.ConfigureAction(services);
var cropCmd = new InferenceCommand(
new InferenceCommandOptions(
"crop",
@@ -277,7 +247,7 @@ static void BuildV2Commands(Command v2Command, IServiceProvider services, string
false,
false));
v2Command.Subcommands.Add(cropCmd);
- cropCmd.ConfigureAction(mindeeV2Client);
+ cropCmd.ConfigureAction(services);
var extractionCmd = new InferenceCommand(
new InferenceCommandOptions("extraction",
"Generic all-purpose extraction.",
@@ -287,7 +257,7 @@ static void BuildV2Commands(Command v2Command, IServiceProvider services, string
true,
true));
v2Command.Subcommands.Add(extractionCmd);
- extractionCmd.ConfigureAction(mindeeV2Client);
+ extractionCmd.ConfigureAction(services);
var ocrCmd = new InferenceCommand(
new InferenceCommandOptions(
"ocr", "OCR utility.",
@@ -297,7 +267,7 @@ static void BuildV2Commands(Command v2Command, IServiceProvider services, string
false,
false));
v2Command.Subcommands.Add(ocrCmd);
- ocrCmd.ConfigureAction(mindeeV2Client);
+ ocrCmd.ConfigureAction(services);
var splitCmd = new InferenceCommand(
new InferenceCommandOptions(
"split",
@@ -308,14 +278,14 @@ static void BuildV2Commands(Command v2Command, IServiceProvider services, string
false,
false));
v2Command.Subcommands.Add(splitCmd);
- splitCmd.ConfigureAction(mindeeV2Client);
+ splitCmd.ConfigureAction(services);
}
static RootCommand BuildCommandLine(IServiceProvider services, string[] args)
{
var root = new RootCommand();
var v1Command = new Command("v1", "Mindee V1 product commands.");
- BuildV2Commands(root, services, args);
+ BuildV2Commands(root, services);
BuildV1Commands(v1Command, services, args);
root.Add(v1Command);
diff --git a/src/Mindee.Cli/README.md b/src/Mindee.Cli/README.md
new file mode 100644
index 000000000..17b0c13c2
--- /dev/null
+++ b/src/Mindee.Cli/README.md
@@ -0,0 +1,116 @@
+# Mindee CLI for .NET
+
+Simple command-line interface for the Mindee APIs.
+
+## Install
+
+```bash
+dotnet tool install --global Mindee.Cli
+mindee -h
+```
+
+## Authentication
+
+Pass your API key with `--api-key`:
+
+- V2: `mindee --api-key ...`
+- V1: `mindee v1 --api-key ...`
+
+You can also configure keys via environment variables:
+
+- V2: `MindeeV2__ApiKey`
+- V1: `Mindee__ApiKey`
+
+## V2 Usage (Latest)
+
+V2 commands are top-level commands:
+
+### Products
+- `classification` : Classify tool
+- `crop` : Crop tool
+- `extraction` : Extraction tool (most common models)
+- `ocr` : OCR tool
+- `split` : Split tool
+
+### Tools
+- `search-models`
+
+### Inference syntax
+
+```bash
+mindee --api-key --model-id [options]
+```
+
+### Search-models syntax
+
+```bash
+mindee --api-key search-models [--name ] [--model-type ] [--raw-json]
+```
+
+### V2 examples
+
+```bash
+# List available extraction models
+mindee --api-key search-models --model-type extraction
+
+# Run an extraction model
+mindee --api-key extraction --model-id ./invoice.pdf --output full --raw-text
+```
+
+## V1 (Legacy)
+
+V1 commands are under the `v1` namespace:
+
+- `barcode-reader`
+- `cropper`
+- `financial-document`
+- `fr-bank-account-details`
+- `fr-carte-grise`
+- `fr-health-card`
+- `fr-carte-nationale-d-identite`
+- `fr-payslip`
+- `international-id`
+- `invoice`
+- `invoice-splitter`
+- `multi-receipts-detector`
+- `passport`
+- `receipt`
+- `us-bank-check`
+
+### General syntax
+
+```bash
+mindee v1 --api-key [options]
+```
+
+### V1 examples
+
+```bash
+# Run invoice parsing
+mindee v1 --api-key invoice ./invoice.pdf --output summary
+
+# Run async receipt parsing and print raw JSON
+mindee v1 --api-key receipt ./receipt.jpg --async --output raw
+```
+
+## Output Modes
+
+For commands that support `--output`:
+
+- `summary`: basic summary (default)
+- `full`: detailed result
+- `raw`: full JSON response
+
+## Help
+
+```bash
+mindee -h
+mindee -h
+mindee v1 -h
+mindee v1 -h
+```
+
+## References
+
+- V2 docs: https://docs.mindee.com/integrations/client-libraries-sdk
+- V1 docs: https://docs.mindee.com/v1/libraries/dotnet-ocr-sdk