OdooKit 2.0.0
dotnet add package OdooKit --version 2.0.0
NuGet\Install-Package OdooKit -Version 2.0.0
<PackageReference Include="OdooKit" Version="2.0.0" />
<PackageVersion Include="OdooKit" Version="2.0.0" />
<PackageReference Include="OdooKit" />
paket add OdooKit --version 2.0.0
#r "nuget: OdooKit, 2.0.0"
#:package OdooKit@2.0.0
#addin nuget:?package=OdooKit&version=2.0.0
#tool nuget:?package=OdooKit&version=2.0.0
OdooKit
A simple, typed .NET client for Odoo's external API: CRUD, wizards, and custom models, built on a swappable transport (classic JSON-RPC today, JSON-2 later) so a future protocol migration doesn't touch the CRUD/wizard logic consumers actually depend on.
Targets netstandard2.0 and net10.0. Set up for AI-driven development
with Claude Code -- see Working with Claude Code
below.
Documentation
- docs/problem-statement.md -- what friction OdooKit removes when integrating a .NET app with Odoo, who it's for, and what it deliberately doesn't solve yet.
- docs/usage.md -- the full how-to-use guide: install, quick start, CRUD, custom (Studio) models, wizards, the typed POCO layer, and error handling.
- docs/enhancement.md -- candidate work beyond the MVP roadmap below, ranked by leverage.
- docs/enhancement-phases.md -- the
phase breakdown for the "traditional ORM vibe" enhancement set
(
OdooContext/DbSet<T>, LINQWhere(), navigation properties), shipped inv1.0.0. - docs/json2-transport-phases.md --
the phase breakdown for implementing the JSON-2 transport adapter
(targeted for
v2.0.0), including the JSON-2 protocol reference (endpoint shape, auth, request/response format).
Architecture: Hexagonal (Ports & Adapters)
Your ASP.NET app
|
v
Application --(IOdooTransport port)--> Domain
^
| implements
Adapters (JsonRpc today, Json2 later)
|
v
Odoo Online
- Domain/ -- entities, wizard result shapes, and the
IOdooTransportport. Zero external dependencies. This is the layer that never changes regardless of which Odoo protocol you're talking to. - Application/ -- the use cases:
OdooClient(public facade),CrudService,WizardOrchestrator,CustomModelAccessor. Depends only on theIOdooTransportinterface in Domain, never on a concrete transport. - Adapters/ -- the only place allowed to know about HTTP, JSON
serialization, or auth.
JsonRpc/is the real, working transport for MVP.Json2/is a deliberate unimplemented stub, kept only to prove the port is genuinely swappable.
Why this structure
The one hard requirement driving this choice: JSON-RPC's classic endpoints
are on a deprecation path (Odoo's own docs say Online instances move off
them around winter 2027), and none of the CRUD/wizard/custom-model logic
should need to be rewritten when that migration happens. Hexagonal is the
one architecture here that enforces that boundary structurally -- via the
compiler, through the IOdooTransport interface -- rather than relying on
discipline to keep transport details from leaking upward.
Roadmap to MVP
Every stub file in this scaffold has a // TODO (Phase N) comment marking
which phase below fills it in. Use .claude/skills/implement-phase N to
work a phase with Claude Code.
Phase 0 -- Protocol spike (no C# yet). Confirm raw /jsonrpc auth + a
simple execute_kw call works against your test instance via curl/Postman.
Done when you have a real request/response pair saved for reference.
Phase 1 -- Transport layer. IOdooTransport + JsonRpcTransport.
Handles auth and wraps execute_kw behind CallAsync<T>(model, method, args, kwargs). Done when a console app can fetch a res.partner record.
Phase 2 -- Core CRUD (dict-based first). Create, Read, Write,
Unlink, Search, SearchRead built purely on IOdooTransport. Handles
field quirks (many2one as [id, name], false vs null) at this layer.
Done when full CRUD round-trips work against both a standard model and a
custom Studio model.
Phase 3 -- Wizard orchestration. The create-wizard-record → call-button-method → resolve-action-dict helper, single-step wizards only. Done when one real wizard runs end-to-end from C#.
Phase 4 -- Minimal typed models. A lightweight POCO + attribute mapping layer on top of the dict-based CRUD. Done when the Phase 2 demo works identically using a typed class instead of dictionaries.
Phase 5 -- Packaging. NuGet packaging, README usage examples. Done
when dotnet add package into a clean ASP.NET project works with the
documented examples unmodified.
Explicitly cut from MVP: the JSON-2 transport implementation (interface is ready, implementation is not), codegen from live Odoo schema, multi-step/chained wizards, batching/bulk-call optimization.
Working with Claude Code
This repo is set up so Claude Code can build it phase-by-phase with minimal re-explaining:
CLAUDE.md-- standing project instructions, loaded every session..claude/rules/-- path-scoped rules that auto-load when Claude touches matching files:hexagonal-boundaries.md(scoped tosrc/),transport-parity.md(scoped tosrc/Adapters/, requires every transport to preserve full typed ORM parity), andtesting.md(scoped totests/)..claude/skills/:/implement-phase <n>-- implements one roadmap phase and its tests, then stops for review./new-adapter <name>-- scaffolds a newIOdooTransportadapter (e.g. the eventual JSON-2 transport) following the JsonRpc pattern./commit-- stages a logical change and drafts a conventional commit message.
.github/workflows/:ci.yml-- build + test on every push/PR.claude.yml--@claudementions in issues/PR comments trigger a Claude Code session (requires anANTHROPIC_API_KEYrepo secret).claude-code-review.yml-- automatic AI review posted on every PR.
Getting started
Add the package to your project:
dotnet add package OdooKit
using System.Net.Http;
using OdooKit.Adapters.JsonRpc;
using OdooKit.Application;
var transport = new JsonRpcTransport(
httpClient: new HttpClient(),
endpoint: new Uri("https://mycompany.odoo.com/jsonrpc"),
database: "mycompany",
login: "admin",
apiKeyOrPassword: "<api-key-or-password>");
var client = new OdooClient(transport);
var partnerId = await client.Crud.CreateAsync("res.partner", new Dictionary<string, object?>
{
["name"] = "Acme Corp",
["is_company"] = true,
});
See docs/usage.md for the full guide: CRUD, custom (Studio) models, wizards, and the typed POCO layer. See docs/problem-statement.md if you want the "why" before the "how."
Building this repo
git clone <your-repo-url>
cd OdooKit
dotnet restore
dotnet build
dotnet test
global.json pins the .NET SDK version so dotnet commands behave the
same on your machine, CI, and in Claude Code's sandbox.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net5.0 was computed. net5.0-windows was computed. net6.0 was computed. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 was computed. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
| .NET Core | netcoreapp2.0 was computed. netcoreapp2.1 was computed. netcoreapp2.2 was computed. netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
| .NET Standard | netstandard2.0 is compatible. netstandard2.1 was computed. |
| .NET Framework | net461 was computed. net462 was computed. net463 was computed. net47 was computed. net471 was computed. net472 was computed. net48 was computed. net481 was computed. |
| MonoAndroid | monoandroid was computed. |
| MonoMac | monomac was computed. |
| MonoTouch | monotouch was computed. |
| Tizen | tizen40 was computed. tizen60 was computed. |
| Xamarin.iOS | xamarinios was computed. |
| Xamarin.Mac | xamarinmac was computed. |
| Xamarin.TVOS | xamarintvos was computed. |
| Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETStandard 2.0
- System.Text.Json (>= 10.0.10)
-
net10.0
- No dependencies.
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.