Odoo reads this file before it imports any of your Python. Get the dictionary wrong and the addon either never appears in Apps or installs without the views and rules you thought you shipped.
A realistic manifest
This one belongs to a small addon that adds a delivery window to quotations, with a report tweak and one OWL widget:
{
"name": "Sale Delivery Window",
"version": "19.0.1.0.0",
"summary": "Agreed delivery window on quotations and the printed PDF",
"author": "Your Company",
"license": "LGPL-3",
"category": "Sales/Sales",
"depends": ["sale"],
"data": [
"views/sale_order_views.xml",
"report/sale_order_templates.xml",
],
"assets": {
"web.assets_backend": [
"sale_delivery_window/static/src/**/*",
],
},
"installable": True,
"application": False,
}
Keys worth knowing
name is the one key Odoo’s documentation marks as required. Set license every time: leave it out and Odoo logs a warning and falls back to LGPL-3. depends lists the modules that must load before yours, and data lists files loaded on install and on every update, in the order written. demo files load only on databases created with demo data. A menu file listed before the file that defines its action is a classic install error. A file missing from the list is worse, because nothing fails: its records just never load.
version accepts x.y, x.y.z, or either of those prefixed with the Odoo series. Short forms get the series added for you, so 1.0 on Odoo 18 is read as 18.0.1.0. We write the full form anyway, because it tells a reader which Odoo the code targets.
assets maps bundle names to file paths or globs. Plain strings append, and tuples give finer control: ("prepend", path), ("before", target, path), ("after", target, path), ("replace", target, path), ("remove", target) and ("include", bundle). JavaScript components and their templates, the OWL side of an addon, normally reach the browser through this key.
Less common but useful: auto_install installs a “link” module automatically once all its dependencies are present (Odoo’s own example is sale_crm), and pre_init_hook, post_init_hook and uninstall_hook name functions in the module’s __init__.py that receive env. Odoo’s docs reserve hooks for setup that is very hard or impossible through the normal API, and we agree.
It’s a literal, not a script
Odoo parses the file with ast.literal_eval. That means plain values only: strings, numbers, booleans, None, and the lists, tuples and dicts built from them. You can’t import a version constant, read a README into description or build the data list in a loop. People try. None of it can work, because nothing in the file is ever executed.
What moved between 17, 18 and 19
The old file name __openerp__.py still loaded in 17 and 18, with a deprecation warning since 17.0. Odoo 19 looks for __manifest__.py only.
Authorship changed too. In 17 and 18, a manifest with no author quietly defaulted to “Odoo S.A.”. Odoo 19 no longer does that. It falls back to contributors or maintainer if present and logs a warning.
The manifests erpfly writes set author, license and a full series version explicitly, and list every dependency the code touches. The rest of the addon structure is covered under Odoo addon, and our Odoo module development service is where the whole thing gets built.