Skip to content

Low-code customization (Studio-style)

Odoo Studio is a visual editor exclusive to Enterprise. The customizations it makes (fields, views, automated actions) are ordinary Odoo records stored in the database. This plugin creates those same records over RPC, so you get the usual Studio results in Community too, without the license.

Honest scope

This covers small, low-code changes: a field, a view tweak, a simple automation. It does not replace serious module development (packaged code, migrations, tests, complex business logic). For that, build a module. See Is it like Odoo Studio?.

Where the changes live

In the instance/database, exactly like Studio, not as module code in a repository. They survive updates as manual customizations. If you need code in a repository, that is module development and falls outside the scope of this plugin.

1. Add a custom field

Use the odoo_add_field tool. It creates a field with state='manual' and forces the required x_ name prefix.

odoo_add_field {
  "model": "res.partner",
  "name": "loyalty_points",
  "label": "Puntos de lealtad",
  "field_type": "integer"
}

The name loyalty_points becomes x_loyalty_points.

Relational example:

odoo_add_field { "model": "res.partner", "name": "account_manager",
  "label": "Ejecutivo de cuenta", "field_type": "many2one", "relation": "res.users" }

For a selection field, pass selection as [["a","A"],["b","B"]]. After creating the field, add it to a form or list view (step 2) so users can see it.

2. Adjust a view (inherited)

There is no dedicated tool; use odoo_create on ir.ui.view with an inherited arch so you do not overwrite the base view. First find the view to extend:

odoo_search_read { "model": "ir.ui.view",
  "domain": [["model","=","res.partner"],["type","=","form"]],
  "fields": ["name","xml_id"], "limit": 5 }

Then create an inherited view:

odoo_create { "model": "ir.ui.view", "values": {
  "name": "res.partner.form.x_loyalty",
  "model": "res.partner",
  "inherit_id": <id_vista_base>,
  "arch_db": "<xpath expr=\"//field[@name='email']\" position=\"after\"><field name=\"x_loyalty_points\"/></xpath>"
}}

Prefer xpath ... position="after|before|inside|replace" instead of rewriting the whole view.

3. Add an automation

Use odoo_add_automation. The Python runs under Odoo's safe_eval; the tool validates it before sending, which matters above all in Odoo online/SaaS, where arbitrary Python is rejected server-side.

odoo_add_automation {
  "model": "crm.lead",
  "name": "Marcar leads calientes",
  "trigger": "on_create_or_write",
  "code": "for rec in records:\n    if rec.probability and rec.probability > 80:\n        rec.priority = '3'"
}

safe_eval rules (enforced by the tool)

The code runs under Odoo's safe_eval. Forbidden: import, def, class, return, with, and access to names or attributes that start with an underscore or dunder (__). The tool rejects those constructs before sending, with a clear remediation, so you find out locally instead of through a server error.

Available names in that context: env, model, record/records, datetime, dateutil, time, UserError. To return an action, assign action = {...} as the last statement (never return).

Enterprise vs Community

  • The fields, views and automations created here work in both editions.
  • In Enterprise they will not appear inside the Studio editor (they are not tagged as web_studio customizations), but they behave the same at runtime.
  • The models exclusive to Enterprise (for example documents.document) still cannot be used in Community: the compatibility layer raises a clear error.

Verify (definition of done)

Read the record back and confirm the effect:

  • Field: odoo_fields_get { "model": "<modelo>" } shows the new x_ field.
  • View: open the form in Odoo (or read the inherited ir.ui.view).
  • Automation: trigger it on a record and read the modified field.

Skill reference: /odoo-tools:odoo-studio-style.