CLI harness for Odoo 12 ERP — CRUD, modules, DB management, reports via XML-RPC. Requires: running Odoo 12 instance
Project description
cli-anything-odoo_12
CLI para Odoo 12 ERP — consulte dados, gerencie módulos, exporte relatórios e faça perguntas em linguagem natural, tudo pelo terminal.
Instalação
Em distros Linux modernas (PEP 668), a solução mais simples é usar pipx, que instala CLIs em ambientes isolados automaticamente:
# Instalar pipx (se ainda não tiver)
sudo apt install pipx
pipx ensurepath
# Instalar o CLI
pipx install cli-anything-odoo-12
# Atualizar para nova versão
pipx upgrade cli-anything-odoo-12
Alternativa com pip (em virtualenv ou sistemas sem PEP 668):
pip install cli-anything-odoo-12
Após instalar, o comando cli-anything-odoo_12 fica disponível no terminal.
Pré-requisitos
- Python 3.10+
- Odoo 12 rodando (acessível via rede, ex:
http://localhost:8069)
Quick Start
1. Connect to Odoo
The CLI supports two backend protocols:
| Backend | Flag | Auth | Requisitos |
|---|---|---|---|
| REST (padrão) | --backend rest |
OAuth2 (client_credentials) | Módulo REST API instalado no Odoo |
| XML-RPC | --backend xmlrpc |
Usuário/senha | Nenhum (nativo do Odoo) |
Opção A: REST API (recomendado)
Requer configuração única do OAuth2:
Passo 1 — Criar Client OAuth2 no Odoo:
- Acesse Configurações > REST API > OAuth2
- Crie um novo client:
- Nome: ex. "CLI API"
- Tipo OAuth:
Client Credentials - Usuário: selecione o usuário Odoo que o client vai operar
- Copie o Client Key e Client Secret
Passo 2 — Configurar o CLI:
cli-anything-odoo_12 config setup-rest \
--client-id <CLIENT_KEY> \
--client-secret <CLIENT_SECRET> \
--url http://localhost:8069 \
--db mydb
Passo 3 — Verificar:
cli-anything-odoo_12 record search res.partner --domain "[('is_company','=',True)]" --limit 5
Opção B: XML-RPC (sem configuração extra)
# Connect via XML-RPC and save credentials
cli-anything-odoo_12 connect \
--url http://localhost:8069 --db mydb --user admin --password admin \
--backend xmlrpc --save
Após configurar (ambos os backends)
# As credenciais são reutilizadas automaticamente nos próximos comandos:
cli-anything-odoo_12 record search res.partner --limit 5
cli-anything-odoo_12 ask "empresas"
# Trocar backend por comando:
cli-anything-odoo_12 --backend xmlrpc record search res.partner --limit 5
# Ou passar credenciais por comando (sobrescreve config salva):
cli-anything-odoo_12 --url http://localhost:8069 --db mydb --user admin --password admin record search res.partner
2. Record Operations (CRUD)
# Search partners (companies only)
cli-anything-odoo_12 record search res.partner --domain "[('is_company','=',True)]" --fields name,email --limit 10
# Example output:
# Found 10 record(s) in res.partner
# [0]
# id: 1
# name: My Company
# email: info@mycompany.com
# [1]
# id: 14
# name: Azure Interior
# email: azure@example.com
# Read specific record
cli-anything-odoo_12 record read res.partner 1 --fields name,email,phone
# Create record
cli-anything-odoo_12 record create res.partner --values '{"name":"New Company","is_company":true}'
# Output: Created res.partner record id=42
# Update record
cli-anything-odoo_12 record write res.partner 42 --values '{"phone":"+55 11 99999-0000"}'
# Delete record
cli-anything-odoo_12 record unlink res.partner 42
# Count records
cli-anything-odoo_12 record count res.partner --domain "[('is_company','=',True)]"
# Output: res.partner: 15 record(s)
# List model fields
cli-anything-odoo_12 record fields res.partner
# Output: res.partner: 143 fields
3. Module Management
cli-anything-odoo_12 module list --installed
# Output: Found 254 module(s)
cli-anything-odoo_12 module list --search sale
cli-anything-odoo_12 module info sale
cli-anything-odoo_12 module install sale
cli-anything-odoo_12 module update sale
4. Database Operations
cli-anything-odoo_12 db list
# Output: Found 3 database(s)
# - erp-production
# - erp-staging
# - test_cli
cli-anything-odoo_12 db create new_db --lang pt_BR
cli-anything-odoo_12 db backup mydb /tmp/mydb_backup.zip
cli-anything-odoo_12 db restore new_db /tmp/mydb_backup.zip
cli-anything-odoo_12 db drop old_db --confirm
5. Reports
cli-anything-odoo_12 report list --model account.invoice
# Output: Found 63 report(s)
cli-anything-odoo_12 report render account.report_invoice 42 --output invoice.pdf
# Output: Report saved: invoice.pdf (45,231 bytes)
6. Data Export
# Export all partners to CSV
cli-anything-odoo_12 export csv res.partner --output partners.csv --fields name,email,phone
# Output: Exported 920 records to partners.csv
# Export with domain filter
cli-anything-odoo_12 export csv res.partner --output companies.csv --fields name,email --domain "[('is_company','=',True)]"
# Output: Exported 15 records to companies.csv
# Export to JSON with limit
cli-anything-odoo_12 export json res.partner --output partners.json --fields name,email --limit 100
# Output: Exported 100 records to partners.json
# Export to stdout (omit --output)
cli-anything-odoo_12 export json res.partner --fields name --limit 3
7. Natural Language Query (NLQ)
The ask command translates free-text queries (PT-BR, EN, ES) into Odoo search domains using regex patterns. No external dependencies or LLM required.
Simple Queries
# List companies
cli-anything-odoo_12 ask "liste todas as empresas"
# Example output:
# ━━━ Empresas ━━━
# Consulta: res.company | 3 registro(s)
#
# ID Nome E-mail Telefone
# ─── ──────────────────── ────────────────── ──────────
# 1 The Cookiery info@cookiery.com (11) 3333-4444
# 3 Filial Centro centro@cookiery.com —
# 5 Filial Shopping shop@cookiery.com —
#
# Total: 3 registro(s)
# Search with filters
cli-anything-odoo_12 ask "faturas de entrada pagas em janeiro/2024"
# Example output:
# ━━━ Faturas de Entrada — Paid — Janeiro/2024 ━━━
# Consulta: account.invoice | 8 registro(s)
#
# ID Numero Parceiro Data Total (R$) Status
# ──── ──────── ───────────────── ────────── ────────── ──────
# 1042 INV/001 Fornecedor ABC 2024-01-05 15.230,00 paid
# 1043 INV/002 Fornecedor XYZ 2024-01-12 8.500,00 paid
# ...
#
# Total: 8 registro(s) | Soma: R$ 87.430,00
# Active customers with limit
cli-anything-odoo_12 ask "clientes ativos" --limit 10
Cross-Model Grouping (Analytical Queries)
Group orders by product category or individual products — the CLI automatically traverses related models (order > line > product > category).
# POS orders grouped by product category
cli-anything-odoo_12 ask "vendas do pos de janeiro/2026 agrupado por categoria de produto"
# Example output:
# ━━━ Vendas do POS — Janeiro/2026 — por Categoria de Produto ━━━
# Consulta: pos.order | 229 itens de linha
#
# Categoria de Produto Itens Qtd Total (R$) %
# ──────────────────── ───── ──── ────────── ────
# Cookies 98 156 2.376,50 67.4%
# Bebidas 45 89 534,20 15.1%
# Salgados 38 62 312,80 8.9%
# Doces 28 45 198,34 5.6%
# Sem Categoria 20 32 106,00 3.0%
#
# Total: 229 itens | Qtd: 384 | Soma: R$ 3.527,84
# POS orders grouped by individual product
cli-anything-odoo_12 ask "vendas do pos agrupado por produto"
# Invoice grouped by product category
cli-anything-odoo_12 ask "faturas agrupado por categoria de produto"
# Purchase orders grouped by product category
cli-anything-odoo_12 ask "pedidos de compra agrupado por categoria de produto"
Supported Cross-Model Groupings
| Model | Group Key | Traversal Path |
|---|---|---|
| pos.order | categoria de produto |
pos.order > pos.order.line > product.product > product.category |
| pos.order | categoria pos |
pos.order > pos.order.line > product.product > pos.category |
| pos.order | produto |
pos.order > pos.order.line > product.product |
| account.invoice | categoria de produto |
account.invoice > account.invoice.line > product.product > product.category |
| account.invoice | produto |
account.invoice > account.invoice.line > product.product |
| sale.order | categoria de produto |
sale.order > sale.order.line > product.product > product.category |
| sale.order | produto |
sale.order > sale.order.line > product.product |
| purchase.order | categoria de produto |
purchase.order > purchase.order.line > product.product > product.category |
Simple Field Grouping
# POS orders grouped by point-of-sale terminal
cli-anything-odoo_12 ask "vendas do pos agrupado por pdv"
# Example output:
# ━━━ Vendas do POS ━━━
# Consulta: pos.order | 50 registro(s)
#
# Grupo Qtd Total (R$) %
# ───────────────── ─── ────────── ────
# Loja Centro 28 4.520,00 65.2%
# Loja Shopping 22 2.410,00 34.8%
#
# Total: 50 registro(s) | Soma: R$ 6.930,00
With Export
# Export to CSV
cli-anything-odoo_12 ask "faturas de entrada em janeiro/2024 e exporte para csv em /tmp/faturas.csv"
# Output: ... Exportado para /tmp/faturas.csv
# Export to JSON
cli-anything-odoo_12 ask "empresas e exporte para json em /tmp/empresas.json"
# Complex combined query with export
cli-anything-odoo_12 ask "faturas de entrada pagas em janeiro/2024 acima de R$ 5.000 e exporte para csv em /tmp/fat.csv"
Other Query Examples
# Birthdays in a specific month
cli-anything-odoo_12 ask "aniversariantes de marco"
# Date range
cli-anything-odoo_12 ask "faturas de 01/03 a 15/03"
# Relative dates
cli-anything-odoo_12 ask "pedidos de compra este mes"
cli-anything-odoo_12 ask "faturas ultimo mes"
# Amount filters (BRL format)
cli-anything-odoo_12 ask "faturas acima de R$ 10.000"
cli-anything-odoo_12 ask "pedidos de venda abaixo de 5000"
# English queries
cli-anything-odoo_12 ask "invoices above 5000"
cli-anything-odoo_12 ask "active customers"
cli-anything-odoo_12 ask "paid invoices in january/2024"
# Spanish queries
cli-anything-odoo_12 ask "facturas pagadas"
Supported Aliases (Multilingual)
| PT-BR | EN | ES | Odoo Model |
|---|---|---|---|
| empresas | companies | — | res.company |
| parceiros, contatos | partners, contacts | socios | res.partner |
| clientes | customers | — | res.partner (customer=True) |
| fornecedores | suppliers | — | res.partner (supplier=True) |
| faturas, notas fiscais | invoices | facturas | account.invoice |
| pedidos de venda | sale orders | pedido de venta | sale.order |
| pedidos de compra | purchase orders | orden de compra | purchase.order |
| produtos | products | — | product.product |
| pagamentos | payments | — | account.payment |
| vendas do pos, pedidos pos | — | — | pos.order |
| usuarios | users | — | res.users |
| aniversariantes | — | — | res.partner (birthday) |
Supported Filters
| Filter | PT-BR | EN |
|---|---|---|
| Status | pagas, em aberto, rascunho, canceladas, confirmadas | paid, open, draft, cancelled, done |
| Type | de entrada, de saida | incoming, outgoing |
| Date | em janeiro/2024, este mes, ultimo mes | in january/2024, this month, last month |
| Range | de 01/03 a 15/03 | from 01/03 to 15/03 |
| Amount | acima de R$ 10.000, abaixo de 5000 | above 5000, below 1000 |
| Boolean | ativos, inativos, arquivados | active, inactive, archived |
| Document | CPF 123.456.789-00 | — |
| Group | agrupado por categoria de produto | grouped by product category |
| Export | exporte para csv em /tmp/f.csv | — |
| Limit | top 10, limitar a 5 | limit 10 |
8. Configuration Management
# Show saved config (passwords/tokens are masked)
cli-anything-odoo_12 config show
# Example output:
# url: http://localhost:8069
# db: erp-thecookiery
# user: nexuz@nexuz.com.br
# password: adm***
# backend: rest
# grant_type: client_credentials
# client_id: vjVaBgp7...
# client_secret: 4EIwDzsN***
# access_token: eyJhbGci***
# token_expiry: 1742060400.0
# Delete a specific key
cli-anything-odoo_12 config delete --key access_token
# Delete all config
cli-anything-odoo_12 config delete
9. JSON Output (for agents)
# Any command with --json produces machine-readable output
cli-anything-odoo_12 --json record search res.partner --limit 3
# Example output:
# {
# "model": "res.partner",
# "count": 3,
# "records": [
# {"id": 1, "name": "My Company", "email": "info@co.com"},
# ...
# ]
# }
cli-anything-odoo_12 --json ask "empresas"
# Cross-group JSON output
cli-anything-odoo_12 --json ask "vendas do pos agrupado por categoria de produto"
# Example output:
# {
# "model": "pos.order",
# "title": "Vendas do POS",
# "group_by": "Categoria de Produto",
# "groups": [
# {"name": "Cookies", "count": 98, "qty": 156.0, "total": 2376.50, "pct": 67.4},
# ...
# ],
# "grand_count": 229,
# "grand_qty": 384.0,
# "grand_total": 3527.84
# }
cli-anything-odoo_12 --json module list --installed
cli-anything-odoo_12 --json db list
10. Interactive REPL
# Start REPL (just run without subcommand)
cli-anything-odoo_12 --url http://localhost:8069 --db mydb --user admin --password admin
# Example session:
# cli-anything-odoo_12 v1.0.0
# Connected to http://localhost:8069 db=mydb uid=2
#
# odoo_12 [mydb] > record search res.partner --limit 5
# Found 5 record(s) in res.partner
# ...
#
# odoo_12 [mydb] > ask "faturas pagas em janeiro/2024"
# ━━━ Faturas — Paid — Janeiro/2024 ━━━
# ...
#
# odoo_12 [mydb] > quit
Global Flags
| Flag | Effect |
|---|---|
--json |
Machine-readable JSON output (all commands) |
--url |
Odoo server URL (overrides saved config) |
--db |
Database name (overrides saved config) |
--user |
Username (overrides saved config) |
--password |
Password (overrides saved config) |
--backend |
Backend protocol: rest (default) or xmlrpc |
Architecture
cli_anything/odoo_12/
├── odoo_12_cli.py # Main CLI entry point (Click framework)
├── core/
│ ├── aliases.py # Multilingual model/status/type alias registry
│ ├── connection.py # Config management + backend factory (get_rpc)
│ ├── cross_group.py # Cross-model grouping engine
│ ├── database.py # Database operations (list, create, backup, etc.)
│ ├── export.py # CSV/JSON export
│ ├── formatters.py # Business-friendly output formatting
│ ├── module.py # Module management
│ ├── nlq.py # Natural Language Query parser (regex-based)
│ ├── record.py # CRUD operations
│ ├── report.py # Report generation
│ └── session.py # Undo/redo + command history
├── utils/
│ ├── odoo_backend_base.py # ABC OdooBackend (21 abstract methods) + config I/O
│ ├── odoo_backend.py # OdooRPC (XML-RPC) + backward-compat re-exports
│ ├── odoo_rest.py # OdooREST (REST API, OAuth2, urllib — zero deps)
│ └── repl_skin.py # Terminal UI (tables, colors, prompts)
└── tests/
├── TEST.md # Test plan + results
├── test_core.py # Unit tests (82 tests, no Odoo needed)
├── test_rest.py # REST backend unit tests (24 tests, mock HTTP)
└── test_full_e2e.py # E2E tests (27 tests, requires running Odoo)
Backend Architecture
All commands work identically regardless of backend. The OdooBackend ABC defines 21 methods
implemented by both OdooRPC (XML-RPC) and OdooREST (REST API):
OdooBackend (ABC)
21 abstract methods
/ \
OdooRPC OdooREST
(xmlrpc.client) (urllib — REST API)
Built-in Odoo API OAuth2 + JSON/HTTP
The connection.py factory (get_rpc()) selects the backend based on saved config or --backend flag.
REST is the default; XML-RPC is available as fallback via --backend xmlrpc.
OAuth2
O CLI utiliza o grant type client_credentials. O client OAuth2 é vinculado a um usuário no Odoo,
e a autenticação usa apenas client_id + client_secret.
O ciclo de vida do token é automático: tokens são persistidos em config.json, renovados na expiração
e re-autenticados em caso de falha (retry em 401).
Troubleshooting
| Problema | Causa | Solucao |
|---|---|---|
Connection refused |
Odoo offline ou URL errada | Verificar se Odoo esta rodando: curl http://localhost:8069/web/login |
Access Denied |
Credenciais invalidas | Verificar usuario/senha: cli-anything-odoo_12 connect --url ... --save |
OAuth2 authentication failed |
client_id/secret incorretos | Verificar OAuth2 client no Odoo (Settings > REST API > OAuth2) |
unauthorized_client |
OAuth Type do client incorreto | No Odoo, verificar se o OAuth Type esta como Client Credentials |
REST API error 500: AccessError |
Usuario REST sem permissoes suficientes | Alterar tipo do usuario para "Usuario Interno" (Settings > Users) |
Modelo nao reconhecido na query |
Alias NLQ nao existe | Usar alias suportado (ver tabela de aliases) ou record search <model> |
command not found |
CLI nao instalado | Executar pip install cli-anything-odoo-12 e verificar which cli-anything-odoo_12 |
404 on /api/* |
Modulo REST API nao instalado | Instalar modulo REST API no Odoo ou usar --backend xmlrpc |
| NLQ retorna 0 registros | Filtros muito restritivos | Simplificar a query (remover filtro de data) e testar incrementalmente |
| Export CSV vazio | Domain sem resultados | Testar a mesma query sem export primeiro para confirmar resultados |
Running Tests
pip install -e ".[dev]"
# Unit tests (no Odoo needed)
python3 -m pytest cli_anything/odoo_12/tests/test_core.py -v
# REST backend unit tests (no Odoo needed — uses mock HTTP)
python3 -m pytest cli_anything/odoo_12/tests/test_rest.py -v
# E2E tests (requires running Odoo)
ODOO_URL=http://localhost:8069 ODOO_DB=mydb ODOO_USER=admin ODOO_PASSWORD=admin \
python3 -m pytest cli_anything/odoo_12/tests/test_full_e2e.py -v -s
# All tests
CLI_ANYTHING_FORCE_INSTALLED=1 python3 -m pytest cli_anything/odoo_12/tests/ -v -s
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file cli_anything_odoo_12-1.0.4.tar.gz.
File metadata
- Download URL: cli_anything_odoo_12-1.0.4.tar.gz
- Upload date:
- Size: 57.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c628ff381f86ecce94d04be5cdb821feeaedfac046de4e07be3c3ab54127ae21
|
|
| MD5 |
6e7ad15179dba53137f0631d5a00296c
|
|
| BLAKE2b-256 |
a2c41d85fcdf6355409ba76a9197a33c4e6a4d18ccf4f1462230f9d9d649e8a8
|
File details
Details for the file cli_anything_odoo_12-1.0.4-py3-none-any.whl.
File metadata
- Download URL: cli_anything_odoo_12-1.0.4-py3-none-any.whl
- Upload date:
- Size: 67.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
eca78154bd15cb9ca12dcf762e15cd8a3cdf3c84e2bcb67b7fb386819b3634f6
|
|
| MD5 |
e3bbe4a253fe7e65d666c9a86c59afff
|
|
| BLAKE2b-256 |
0d8709fdde69f030ecc9a2addec28a013920d20786b26dab85214d5625c178a6
|