Skip to content
| Marketplace
Sign in
Visual Studio Code>Programming Languages>OdooLensNew to Visual Studio Code? Get it now.
OdooLens

OdooLens

AnandShah

| (0) | Free
Odoo-aware developer intelligence for VS Code: semantic model index, ORM performance doctor, XML view validation, security analysis, dependency graphs, migration assistant and more.
Installation
Launch VS Code Quick Open (Ctrl+P), paste the following command, and press enter.
Copied to clipboard
More Info

OdooLens

Odoo-aware developer intelligence for Visual Studio Code

License: MIT TypeScript VS Code Odoo GitHub stars GitHub issues

VS Code finally understands Odoo.

OdooLens (Odoo Intelligence) gives the editor real, structural understanding of an Odoo codebase: the ORM model registry, field and method inheritance, XML view inheritance, manifests, dependencies, security patterns, QWeb reports, and more — not a generic Python linter with a few Odoo-flavored regexes bolted on.

Everything the extension does — autocomplete, hover, go-to-definition, find references, rename, the ORM performance doctor, the security analyzer, XML and QWeb validation, dependency graphs, impact analysis, migration reports, and optional runtime registry inspection — is powered by one shared semantic index. See ARCHITECTURE.md for the full design.

Made with ❤️ by Anand Shah for the developer community.


Why OdooLens?

Challenge What OdooLens does
Dynamic ORM (self.env['x'], inheritance, related fields) Builds a merged model index across modules
N+1 searches and loop-bound ORM ORM Doctor with confidence-scored diagnostics
XML fields and buttons that don't exist Static XML + QWeb validation against the index
sudo(), public routes, ACL gaps Security and ACL analyzers
Upgrades across 14→19 Data-driven migration rules with report output
"Who calls this method?" Impact analysis, references, and dependency graphs

Features

  • Semantic model intelligence — fields, methods, _inherit / _inherits, compute/depends, controllers
  • Language features — completion, hover (with real usage counts), definition, references, symbols, rename
  • ORM Query Doctor — search/browse/create/write/unlink in loops, nested loops, mapped/filtered patterns, repeated searches, and more
  • Security analyzer — sudo(), unrestricted search, public controller mutations, CSRF, ACL/record rules
  • XML & QWeb validation — missing fields/methods, XPath targets, duplicate IDs, unresolved refs, version-aware attributes, t-field / t-call
  • Dead-code hints — fields, private methods, models, imports, modules, reports, XML IDs (conservative confidence)
  • Dependency & view graphs — interactive webviews for modules, models, and view inheritance chains
  • Migration assistant — verified rules for Odoo 14 through 19
  • Impact analysis — overrides, call sites, XML buttons
  • Log navigator — paste a traceback, jump to source, aggregate recurring errors
  • Optional runtime registry — compare static index to a live Odoo instance (credentials via SecretStorage)

Quick start

From source

git clone https://github.com/AnandShah10/OdooLens.git
cd odoolens
npm install
npm run compile
npm test

Open the folder in VS Code and press F5 to launch an Extension Development Host with OdooLens active.

Or package and install a .vsix:

npx vsce package
code --install-extension odoolens-*.vsix

Activate on an Odoo project

Open a workspace that contains one or more Odoo modules (any directory with a __manifest__.py). OdooLens activates automatically (workspaceContains:**/__manifest__.py) and runs an initial workspace analysis.


Supported Odoo versions

The static analyzers (model/field/XML parsing, ORM doctor, security analyzer, XML validator) are version-agnostic — they work on the Python/XML syntax patterns Odoo has used since v8+.

Version-aware behavior lives specifically in the migration assistant (src/versioning/MigrationRules.ts), which currently ships verified rules for:

From To Example rules
14 15 @api.multi/@api.one removal, track_visibility → tracking
15 16 args= renamed to domain= on search()/search_count()/_search(), fields_get_keys()/get_xml_id() deprecated, _mapped_cache() removed, Model._sequence removed, Field.column_format/Field.deprecated removed
16 17 name_get() deprecation warning, attrs="..." view syntax deprecation
17 18 <tree> → <list> view tag and view_mode tree → list (XML and Python action dicts), sudo(True/False) boolean-argument deprecation, check_access_rights()/check_access_rule() superseded by unified check_access()
18 19 read_group() deprecated in favor of _read_group()/formatted_read_group(), legacy odoo.osv import path deprecated, self._cr/self._uid/self._context deprecated in favor of self.env.cr/self.env.uid/self.env.context

Every rule above was sourced from Odoo's official ORM changelog (odoo.com/documentation/.../developer/reference/backend/orm/changelog.html) with a PR reference, not inferred from memory — each rule's documentationUrl points at the specific page.

Set odooIntelligence.odooVersion to a specific version, or leave it "auto". New rules are added as plain data entries in MigrationRules.ts, never as ad-hoc logic — see CONTRIBUTING.md.

Configuration

All settings live under the odooIntelligence.* namespace (see package.json → contributes.configuration for the authoritative list). Highlights:

  • odooIntelligence.addonsPaths — extra addons paths to scan (relative to the first workspace folder, or absolute), beyond the open workspace folders themselves — e.g. a separate enterprise/ or custom-addons/ checkout.
  • odooIntelligence.odooVersion — "auto" (default) auto-detects the workspace's Odoo version from module manifests' version fields and uses it as the default "from" version in Odoo: Generate Migration Report; set a specific version (e.g. "17") to skip that prompt entirely.
  • odooIntelligence.enableORMDoctor / enableSecurityAnalyzer / enableXMLAnalyzer / enableDeadCodeAnalyzer / enableMigrationAnalyzer / enableRuntimeRegistry — per-analyzer toggles. enableMigrationAnalyzer/enableRuntimeRegistry gate their respective commands directly (they'll tell you they're disabled rather than silently doing nothing).
  • odooIntelligence.logLevel — error | warning | information (default) | hint; controls how much OdooLens writes to the "OdooLens" output channel. Set to error to silence routine "indexed N modules" logging and keep only real failures.
  • odooIntelligence.ormDoctor.rules — an object map to disable individual ORM Doctor rules (e.g. {"search-in-loop": false}).
  • odooIntelligence.security.rules — per-code-pattern toggles (sudo-bypass, unrestricted-search, public-controller-mutation, csrf-disabled-route, sudo-mutation-without-auth-check).
  • odooIntelligence.security.aclRules — per-configuration-check toggles for the ACL/record-rule analyzer (no-access-rule-defined, dangling-access-rule-model, acl-write-without-read, permissive-record-rule).
  • odooIntelligence.deadCode.minConfidence — definitely_unused | probably_unused | unknown; OdooLens currently never emits definitely_unused (see Limitations).

Commands

Command What it does
Odoo: Analyze Workspace / Odoo: Rebuild Index Full workspace scan: discovers modules, parses every .py/.xml/ir.model.access.csv, builds the merged model index, runs all analyzers. Python analyses are cached across sessions (see below) — a repeat scan of an unchanged workspace should be noticeably faster than the first one.
Odoo: Clear Index Cache Deletes the persistent cache so the next rebuild re-parses every Python file from scratch. Shouldn't normally be needed (file-mtime invalidation handles changes automatically) — here as a manual escape hatch.
Odoo: Show Model Webview listing every field/method on a chosen model, with declaring module + file.
Odoo: Show Field Intelligence Field-level detail: type, compute/depends chain, declaration history across modules, static usage counts. Works from the cursor position or via picker.
Odoo: Find Field Usages Opens VS Code's built-in "references" peek view for a chosen field's statically-discovered usages.
Odoo: Go to Field Definition Jumps straight to a field's declaring source line.
Odoo: Show Dependency Graph Interactive pan/zoom/click SVG graph, three modes: module dependency graph; per-model relationship graph (contributing modules, related comodels, views); or the unified model graph — one graph spanning every field, method, view, scheduled action (ir.cron), server action, and security rule (ir.model.access.csv + ir.rule) for a model, grouped under category nodes.
Odoo: Show View Inheritance Resolves a chosen base view's full <xpath>/position inheritance chain into an effective tree, with per-node provenance badges and unresolved-target warnings.
Odoo: Analyze Impact For a model method, shows override history, direct Python call sites, and XML button references — all from the shared index.
Odoo: Generate Migration Report Scans every indexed Python file against the structured migration rule set for a chosen version range.
Odoo: Connect to Runtime / Odoo: Inspect Runtime Registry Optional live-server comparison (see below).
Odoo: Analyze Odoo Log Parses a pasted/opened server log into structured, de-duplicated error occurrences.

Beyond commands, OdooLens also registers standard VS Code language features you don't need a command for: completion/hover/go-to-definition (Python), a workspace symbol provider (Ctrl+T / Cmd+T — search for any indexed model/field/method by name), a CodeActionProvider (lightbulb quick fixes for ORM Doctor findings + "learn more" links), and a rename provider (F2 on a field, a method, or a model-name string — see Limitations below for exactly what each of the three does and deliberately does not rename).

Sidebar explorers

OdooLens adds an OdooLens icon to the activity bar with three tree views, all refreshing automatically as the index or diagnostics change:

  • Models — every indexed model, expandable into its Fields (with type/comodel) and Methods (with decorators); click any node to jump to its declaration.
  • Modules — modules in dependency order, expandable into the models each contributes to and the modules it depends on (dependencies outside the workspace are marked).
  • Problems — OdooLens's own findings grouped by category (security first), unlike VS Code's built-in Problems panel which groups by file. Hover a finding for its message and confidence level.

Example diagnostics

ORM Doctor (search-in-loop):

⚠ Possible N+1 ORM query: search() executes once per loop iteration. Consider batching:
collect the relevant IDs first, then run a single search() with an 'in' domain outside
the loop. [medium confidence]

XML validator (xml-field-not-found):

Field "customer_score" does not exist on model "sale.order" (as resolved by the static
index). If this field is added dynamically or by a module outside the current workspace,
this may be a false positive. [high confidence]

Security analyzer (sudo-bypass):

sudo() bypasses normal record rules and access rights for every ORM call chained after it.
Verify that the intended authorization scope is deliberate and as narrow as possible.
[medium confidence]

Security analyzer, auth-escalated (sudo-bypass from a public route):

sudo() is called from a route with auth='public' — this combination (unauthenticated caller
+ elevated ORM privileges) is the classic shape of an access-control vulnerability. Verify
every ORM call between here and the route's mutations is scoped as narrowly as possible.
[high confidence]

ACL analyzer (no-access-rule-defined):

Model "custom_sale.log" has no ir.model.access.csv row anywhere in the indexed workspace.
Without an access rule, users typically cannot read/write this model at all (Odoo defaults
to no access). [medium confidence]

Runtime integration (optional)

OdooLens works fully offline from the static index. Optionally, it can compare that against a live Odoo server's registry: install the companion module in odoo-helper/ (see its README — copy odoolens_helper/ into an addons path, set the odoolens.api_token system parameter), enable odooIntelligence.enableRuntimeRegistry, then run Odoo: Connect to Runtime. Odoo: Inspect Runtime Registry then shows STATIC INDEX vs RUNTIME REGISTRY for a model side by side. The token lives in VS Code SecretStorage only — never logged, never in settings. The helper is read-only, refuses every request until a token is configured, and is meant for development/staging databases. No telemetry is sent anywhere by default.

The VS Code client and the helper's introspection logic are both tested (against a fake HTTP endpoint and plain-Python fakes respectively), but the helper's thin Odoo controller has not been run against a real Odoo server in this project's build environment — treat a first real connection as the final verification step.

Known limitations (read this before trusting a diagnostic blindly)

OdooLens is upfront about where static analysis cannot be perfect — see ARCHITECTURE.md § Limitations for the full list. In short:

  • No full type inference. self.env['x.y'] and self. inside a known model's method are resolved with high confidence; an arbitrary local variable is resolved only via a one-hop heuristic (var = self.env[...], or for x in var). Anything else yields no completion rather than a guess.
  • XPath support is a practical subset: //tag[@attr='value'] and shorthand position="..." patches. General XPath axes/functions are not implemented.
  • Usage/reference counts follow multi-hop attribute chains, multi-segment for-loop iterables, and CHAINS of type-preserving method calls (self.partner_id.name, for child in self.partner_id.child_ids:, var = var.filtered(...).sorted(...).exists(), var = var.mapped('child_ids')) — still not full type inference. See ARCHITECTURE.md § Reference/usage counting for the whitelisted method set and exactly what remains unresolved.
  • Dead-code findings never claim "definitely unused" — only probably_unused or unknown.
  • Incremental indexing recomputes only the affected models on each file save (debounced) — both the merged model index (incrementalRebuildModels()) and the cross-file reference index (buildReferenceIndex(onlyModels)) are scoped to the models the changed file's contributions or views actually touch, leaving every other model's data untouched.
  • Impact analysis follows direct self.method(...) calls, XML <button> references, and (via a text search) ir.cron / ir.actions.server code fields — but not dynamic dispatch (getattr, etc.). It cannot enumerate actual external RPC callers (that's unknowable from source code alone); instead it reports the concrete static fact it CAN know — whether the method is RPC-reachable at all (public name with no @api.private).
  • Rename covers three symbol kinds, each scoped to only what OdooLens can pinpoint exactly:
    • Field: every declaration site across inheriting modules, plus any XML <field name="..."> usage on a view whose model matches.
    • Method: every declaration/override site, plus any XML <button name="..." type="object"> reference. Does NOT rename self.method_name() call sites (OdooLens tracks that such calls exist, but not their exact source location).
    • Model (F2 on a model-name string, e.g. inside _name = "..." or self.env['...']): every _name/_inherit string-literal contents and every self.env['...'] string. Does NOT rename XML <field name="model">, ir.model.access.csv rows or their model_<name> external-id convention, or other cross-references — model rename has a much larger blast radius (a mismatched external id can break module installation), so you're told to search for the old name and finish the rest by hand. None of the three rename Python attribute access or domain tuples, since those come from the best-effort reference index rather than exact AST locations.
  • The npm run test:integration VS Code integration suite needs normal internet access on first run (to download a VS Code test binary) — see ARCHITECTURE.md § Testing strategy if it fails inside a network-restricted sandbox/CI image.

Troubleshooting

  • "No models found": confirm the open folder (or a subfolder within addonsPaths) actually contains __manifest__.py files, and run Odoo: Rebuild Index manually.
  • A field/method shows as missing but you know it exists: it's likely declared in a module that isn't inside your current workspace (e.g. Odoo core sale, stock, etc.). OdooLens only indexes what it can see; add the missing addons path via odooIntelligence.addonsPaths if it's on disk, and re-run "Rebuild Index".
  • Parsing seems to skip a file: check the "OdooLens" output channel — malformed Python/XML is logged and skipped rather than crashing the extension.
  • Contact us
  • Jobs
  • Privacy
  • Manage cookies
  • Terms of use
  • Trademarks
  • Your Privacy Choices
  • Consumer Health Privacy
© 2026 Microsoft