Is there an LLM trained on Odoo's source? Probably not the one you want
No public model is fine-tuned on Odoo 19 source. Here's why, and the RAG setup that actually fixes Cursor's stale answers.
The short answer is no — not in the way you mean. There is no publicly available LLM that has been fine-tuned on the Odoo 19 codebase and ships with up-to-date knowledge of _inherit quirks, the new OWL bindings, or whatever changed in account.move between 18 and 19. The reason isn’t that nobody tried. It’s that fine-tuning is the wrong tool for the job, and the people who could afford to do it well have all quietly settled on retrieval instead.
If Cursor is giving you Odoo 16 answers when you’re working in 19, the fix is not finding a better-trained model. The fix is making sure the model never has to remember Odoo at all.
Why a “trained on Odoo” model doesn’t really exist
A fine-tuned model is a snapshot. Odoo isn’t. The 19.0 branch had several hundred commits in its first month after release, and the OCA repos move faster than that. Any model you fine-tune today is wrong by next Tuesday. The companies running frontier models know this — it’s why GPT-5 and Claude 4 are aggressive about their training cutoffs but soft on the parts of their training that go stale fastest. They learn the shape of frameworks and let retrieval fill in the specifics.
There have been a few community attempts. Someone on Hugging Face uploaded a LoRA fine-tune of a 7B model on the Odoo 16 codebase a couple of years back. It was worse than vanilla Llama at writing Odoo modules, because a 7B model with extra Odoo bias still couldn’t reason about ORM semantics. Fine-tuning teaches a model surface patterns; it doesn’t teach a model that flushes are eager but cache invalidations aren’t.
Odoo S.A. could in theory train and host one. They haven’t, and the pragmatic guess is they won’t. Their commercial focus is the platform itself, not selling tooling for people who want to write modules outside the partner program.
What Cursor is actually doing
When you ask Cursor a question, it uses one of a handful of base models (Claude, GPT, sometimes a smaller code-specific one) plus whatever context it can scrape from your open files and indexed workspace. If Odoo isn’t in your workspace, the model is reasoning purely from training data — which for most current models, is solid on Odoo 13 through 16, partial on 17, thin on 18, and basically nonexistent on 19.
The dated responses you’re seeing are not a model bug. They’re a context bug. Cursor sees from odoo import models and the model assumes whatever it knew about Odoo at training time still applies. It will happily invent a method signature that was correct in Odoo 15 and removed in 17.
The fix is to make the source code part of the conversation.
What actually works
Three approaches, in increasing order of effort.
1. Index the Odoo source as a workspace folder. This is the cheapest and most underused. Clone the version of Odoo you’re targeting alongside your custom modules:
mkdir -p ~/code/odoobro && cd ~/code/odoobro
git clone --depth 1 -b 19.0 https://github.com/odoo/odoo.git
git clone --depth 1 -b 19.0 https://github.com/odoo/enterprise.git # if you have access
git clone ./your-custom-modules
Open the parent folder in Cursor. Cursor’s indexer will read all of it. When you ask “how does account.move._post work in 19,” the model now has the actual source in context. Same trick works in VS Code with Continue, in Zed, and in any editor with workspace-aware AI.
The downside: indexing 150k files of Odoo source is heavy. Add a .cursorignore (or equivalent) to skip what you don’t need:
odoo/addons/website_*/
odoo/addons/theme_*/
odoo/addons/l10n_*/
**/static/lib/
**/i18n/
**/*.po
You almost never need themes or localizations in context, and the static lib folders are mostly bundled JS that will eat your token budget.
2. Use an MCP server that exposes Odoo’s source as a tool. The Model Context Protocol is the right shape for this problem. A small MCP server can expose search_odoo_source(query, version) and read_odoo_file(path) as tools, and any MCP-aware client (Claude Desktop, Cursor in agent mode, the Claude Code CLI) can call them on demand.
A minimal version is about 80 lines of Python around ripgrep and pathlib. The community has shipped a few — search “odoo mcp server” on GitHub. The one I’ve gotten the most mileage out of indexes both core and OCA, and lets the model query by model name (account.move), method name (_post), or free text.
The advantage over option 1: the model only loads the chunks it actually needs, so you can index every OCA repo without blowing your context window.
3. Run a local RAG with embeddings over the source. This is the heaviest setup and the one that pays off if you’re doing a lot of cross-version work. Embed the Odoo source — split per function and per ORM model — into a vector store (Chroma, Qdrant, pgvector — any of them work). When you ask a question, retrieve the top 20 chunks and stuff them into the prompt.
The reason this is better than workspace indexing is semantic search: “how does Odoo handle deferred revenue” finds account.move, account.move.line, and the _compute_amount_residual chain even though none of them contain the phrase “deferred revenue.” Workspace indexing is keyword-only.
The reason it’s worse: it’s another moving part. If your embeddings are stale, your answers are stale. Re-embedding the whole 19.0 branch is a 30-minute job on a modest machine.
The honest middle ground
For a working Odoo developer doing day-to-day module work, option 1 is enough. Clone the source, ignore the noise, and let Cursor index it. Your model goes from guessing what account.move._post looks like in 19 to reading it. That alone fixes most of the “dated responses” problem.
Reach for MCP or RAG when you start asking cross-cutting questions — “where in core is the picking_type_id default actually computed” — and grep-on-workspace stops being enough.
When a fine-tune would actually be worth it
If you’re maintaining a fork of Odoo with 200+ custom modules and a house style that diverges from upstream, a small fine-tune on your own code can teach the model your conventions: how you name fields, how you handle migrations, which OCA modules you’ve banned. That’s a real use case. But it complements retrieval; it doesn’t replace it. The model still needs the current source in context to write code that actually runs.
What to do if you’re hitting this right now
Try option 1 today. It takes ten minutes and a .cursorignore. If the answers are still wrong, the problem is probably not the model — it’s that you’re asking a question whose answer lives in a file the model hasn’t loaded. Open the relevant file in a tab, or paste the model definition into your prompt. Cursor and Claude both write very competent Odoo 19 code when they’re looking at the actual Odoo 19 code.
The framing that helps: don’t think of the model as something that knows Odoo. Think of it as a senior engineer who is fast at reading source files but has never seen this codebase before. That’s roughly the truth, and it tells you exactly what to put in front of them.