@marcfargas/odoo-cli 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/README.md +354 -0
  2. package/package.json +53 -53
package/README.md ADDED
@@ -0,0 +1,354 @@
1
+ # `@marcfargas/odoo-cli`
2
+
3
+ [![npm](https://img.shields.io/npm/v/@marcfargas/odoo-cli)](https://www.npmjs.com/package/@marcfargas/odoo-cli)
4
+ [![License: LGPL-3.0](https://img.shields.io/badge/License-LGPL--3.0-blue.svg)](https://www.gnu.org/licenses/lgpl-3.0)
5
+
6
+ Command-line interface for Odoo ERP — query records, post chatter messages, manage modules, track time, inspect schema, and more. Built on [`@marcfargas/odoo-client`](../odoo-client).
7
+
8
+ ---
9
+
10
+ ## Installation
11
+
12
+ ```bash
13
+ npm install -g @marcfargas/odoo-cli
14
+ ```
15
+
16
+ Installs the `odoo` binary (also available as `odoo-cli`).
17
+
18
+ ---
19
+
20
+ ## Configuration
21
+
22
+ All commands read credentials from environment variables. Set them once in your shell profile:
23
+
24
+ ```bash
25
+ export ODOO_URL=https://mycompany.odoo.com
26
+ export ODOO_DB=mycompany
27
+ export ODOO_USERNAME=admin@example.com
28
+ export ODOO_PASSWORD=secret
29
+ ```
30
+
31
+ | Variable | Description | CLI flag override |
32
+ |---|---|---|
33
+ | `ODOO_URL` | Odoo base URL | `--url` |
34
+ | `ODOO_DB` | Database name | `--db` |
35
+ | `ODOO_USERNAME` | Login username | `--user` |
36
+ | `ODOO_PASSWORD` | Password | `--password` |
37
+
38
+ Verify your connection:
39
+
40
+ ```bash
41
+ odoo config check
42
+ odoo config show # shows resolved config (password redacted)
43
+ odoo config show --format json
44
+ ```
45
+
46
+ > **Note:** Prefer environment variables over CLI flags — flags appear in shell history.
47
+
48
+ ---
49
+
50
+ ## Quick Start
51
+
52
+ ```bash
53
+ # Search records with filters
54
+ odoo records search crm.lead --fields id,name,stage_id --limit 20
55
+ odoo records search res.partner --filter active=true --format csv > partners.csv
56
+
57
+ # Post an internal note on a record
58
+ odoo mail note crm.lead 42 "Called customer, following up next week" --confirm
59
+
60
+ # Stream all invoices as newline-delimited JSON
61
+ odoo records search account.move --domain '[("state","=","posted")]' --all --format ndjson \
62
+ > invoices.ndjson
63
+
64
+ # Generate a TypeScript interface for a model
65
+ odoo schema codegen sale.order --out ./types/sale-order.ts
66
+ ```
67
+
68
+ ---
69
+
70
+ ## Commands Reference
71
+
72
+ ### `odoo config` — Connection management
73
+
74
+ ```
75
+ odoo config check Verify connection and show current user [READ]
76
+ odoo config show Show resolved config (password redacted) [READ]
77
+ ```
78
+
79
+ ### `odoo records` — Generic CRUD on any Odoo model
80
+
81
+ ```
82
+ odoo records search <model> Filter and list records [READ]
83
+ odoo records get <model> <id> Fetch a single record [READ]
84
+ odoo records count <model> Count matching records [READ]
85
+ odoo records create <model> Create a record [WRITE]
86
+ odoo records write <model> <ids> Update records — batch by comma-separated IDs [WRITE]
87
+ odoo records delete <model> <ids> Delete records [DESTRUCTIVE]
88
+ odoo records call <model> <method> Call an arbitrary model method [WRITE]
89
+ ```
90
+
91
+ `search` supports rich filtering:
92
+
93
+ ```bash
94
+ # Odoo domain syntax
95
+ odoo records search sale.order --domain '[("state","=","sale")]'
96
+
97
+ # JSON domain
98
+ odoo records search sale.order --domain-json '[["state","=","sale"]]'
99
+
100
+ # Simple K=V shorthand (ANDed, repeatable)
101
+ odoo records search res.partner --filter active=true --filter country_id.code=ES
102
+
103
+ # Domain from file or stdin
104
+ odoo records search crm.lead --domain-file filter.json
105
+
106
+ # Pagination
107
+ odoo records search res.partner --limit 200 --offset 0 --order "name asc"
108
+ odoo records search account.move --all --page-size 500 # fetches everything, paged
109
+ ```
110
+
111
+ `call` invokes arbitrary ORM methods:
112
+
113
+ ```bash
114
+ odoo records call sale.order action_confirm --ids 42 --confirm
115
+ odoo records call sale.order get_delivery_count --ids 42 --read-only # no --confirm needed
116
+ ```
117
+
118
+ ### `odoo mail` — Chatter messages
119
+
120
+ ```
121
+ odoo mail note <model> <id> [message] Post internal note — staff only [WRITE]
122
+ odoo mail post <model> <id> [message] Post public message — notifies followers [WRITE]
123
+ ```
124
+
125
+ ```bash
126
+ odoo mail note crm.lead 42 "Meeting rescheduled" --confirm
127
+ odoo mail post sale.order 88 "Your order has shipped" --confirm
128
+
129
+ # HTML body
130
+ odoo mail note project.task 17 "<p>Build <strong>passed</strong></p>" --html --confirm
131
+
132
+ # Read message from file or stdin
133
+ git log --oneline -5 | odoo mail note project.task 17 --message-file - --confirm
134
+
135
+ # With subject and explicit partner notifications
136
+ odoo mail post crm.lead 42 --subject "Contract ready" --partner-ids 7,15 "See attached." --confirm
137
+ ```
138
+
139
+ ### `odoo modules` — Module management
140
+
141
+ ```
142
+ odoo modules list List modules [READ]
143
+ odoo modules info <name> Show module metadata [READ]
144
+ odoo modules status <name> Print single-word state — for scripting [READ]
145
+ odoo modules install <name> Install a module [WRITE]
146
+ odoo modules upgrade <name> Upgrade a module [WRITE]
147
+ odoo modules uninstall <name> Uninstall — may remove data [DESTRUCTIVE]
148
+ ```
149
+
150
+ ```bash
151
+ odoo modules list --filter installed
152
+ odoo modules list --search sale --format json | jq '.[].technical_name'
153
+ odoo modules status hr_timesheet # prints: installed
154
+
155
+ if [ "$(odoo modules status my_addon)" = "installed" ]; then echo ready; fi
156
+ ```
157
+
158
+ ### `odoo attendance` — Clock in/out *(requires `hr_attendance`)*
159
+
160
+ ```
161
+ odoo attendance clock-in Record clock-in [WRITE]
162
+ odoo attendance clock-out Record clock-out [WRITE]
163
+ odoo attendance status Show current attendance status [READ]
164
+ odoo attendance list List records by date range [READ]
165
+ ```
166
+
167
+ ```bash
168
+ odoo attendance clock-in --confirm
169
+ odoo attendance status
170
+ odoo attendance list --from 2024-03-11 --to 2024-03-15 --format csv
171
+ ```
172
+
173
+ Use `--employee-id <n>` or `--employee <name>` to act on behalf of another employee (default: current user).
174
+
175
+ ### `odoo timesheets` — Time tracking *(requires `hr_timesheet`)*
176
+
177
+ ```
178
+ odoo timesheets start Start a timer [WRITE]
179
+ odoo timesheets stop Stop running timer [WRITE]
180
+ odoo timesheets running Show running timer [READ]
181
+ odoo timesheets log Log time retroactively [WRITE]
182
+ odoo timesheets list List timesheet entries [READ]
183
+ ```
184
+
185
+ ```bash
186
+ # Timer workflow
187
+ odoo timesheets start --task-id 42 --description "Feature work" --confirm
188
+ odoo timesheets running
189
+ odoo timesheets stop --confirm
190
+
191
+ # Manual entry
192
+ odoo timesheets log --task-id 42 --hours 1.5 --description "Review PR" --confirm
193
+ ```
194
+
195
+ ### `odoo accounting` — Read-only accounting queries *(requires `account`)*
196
+
197
+ All commands are READ-only — no `--confirm` required.
198
+
199
+ ```
200
+ odoo accounting cash-accounts Discover cash/bank journal accounts
201
+ odoo accounting cash-balance Show balance as-of a date
202
+ odoo accounting posted-moves List posted journal entries
203
+ odoo accounting trace-recon <id> Show reconciliation for a move
204
+ odoo accounting days-to-pay <id> Payment term analysis for an invoice
205
+ ```
206
+
207
+ ```bash
208
+ odoo accounting cash-balance --as-of 2024-03-31
209
+ odoo accounting posted-moves --from 2024-01-01 --to 2024-03-31 --format csv
210
+ ```
211
+
212
+ ### `odoo url` — Generate record URLs
213
+
214
+ ```
215
+ odoo url record <model> <id> Backend URL [READ]
216
+ odoo url portal <model> <id> Portal URL [READ]
217
+ ```
218
+
219
+ ```bash
220
+ URL=$(odoo url record project.task 17)
221
+ odoo mail note project.task 17 "Deployed: $URL" --confirm
222
+ ```
223
+
224
+ ### `odoo schema` — Runtime schema introspection
225
+
226
+ Wraps [`@marcfargas/odoo-introspection`](../odoo-introspection). All commands are READ.
227
+
228
+ ```
229
+ odoo schema models List all models
230
+ odoo schema fields <model> List fields for a model
231
+ odoo schema describe <model> Human-readable model summary
232
+ odoo schema codegen <model> Generate TypeScript interface
233
+ ```
234
+
235
+ ```bash
236
+ odoo schema models --search sale
237
+ odoo schema fields crm.lead --type many2one
238
+ odoo schema describe res.partner
239
+ odoo schema codegen sale.order --out ./types/sale-order.ts
240
+ ```
241
+
242
+ ### `odoo state` — ⚠ Experimental state management
243
+
244
+ Declare desired Odoo configuration, plan drift, and apply — similar to Terraform. All commands require `--experimental`.
245
+
246
+ ```
247
+ odoo state plan <file> Show drift between desired and current [READ]
248
+ odoo state diff <model> Show current state of a model's records [READ]
249
+ odoo state apply <file> Apply desired state [WRITE]
250
+ ```
251
+
252
+ ```bash
253
+ odoo state plan ./config.json --experimental
254
+ odoo state apply ./config.json --experimental --confirm
255
+ ```
256
+
257
+ ---
258
+
259
+ ## Output Formats
260
+
261
+ ```bash
262
+ odoo records search crm.lead --format json # JSON array
263
+ odoo records search crm.lead --format table # ASCII table (default in TTY)
264
+ odoo records search crm.lead --format csv # CSV with header row
265
+ odoo records search crm.lead --format ndjson # Newline-delimited JSON (streaming)
266
+ ```
267
+
268
+ **Auto-detection:** when stdout is a TTY, defaults to `table`; when piped, defaults to `json`.
269
+
270
+ **stdout / stderr split:**
271
+
272
+ - `stdout` — data only (always parseable, safe to pipe)
273
+ - `stderr` — errors, progress messages, warnings
274
+
275
+ This means `odoo records search crm.lead | jq '.[0].name'` always works even in `table` mode, because table output also goes to stdout only when a TTY is detected.
276
+
277
+ ---
278
+
279
+ ## Safety Model
280
+
281
+ Every command has a safety level shown in its description:
282
+
283
+ | Level | What it means | Requirements |
284
+ |---|---|---|
285
+ | **READ** | No data mutation | None — safe to run anywhere |
286
+ | **WRITE** | Creates or updates Odoo records | `--confirm` required |
287
+ | **DESTRUCTIVE** | May permanently delete data | `--confirm` required, warning printed |
288
+
289
+ ```bash
290
+ # This will error: --confirm is required
291
+ odoo records create res.partner --data '{"name":"Acme"}'
292
+
293
+ # Correct
294
+ odoo records create res.partner --data '{"name":"Acme"}' --confirm
295
+
296
+ # Preview without executing (no --confirm needed)
297
+ odoo records create res.partner --data '{"name":"Acme"}' --dry-run
298
+ ```
299
+
300
+ `--dry-run` prints the RPC call that *would* be executed to stderr and exits without contacting Odoo. Use it to verify commands before committing to mutations.
301
+
302
+ `--read-only` is accepted by `records call` to declare that a method is safe (skips the `--confirm` check).
303
+
304
+ ---
305
+
306
+ ## Global Flags
307
+
308
+ These flags work on every command:
309
+
310
+ | Flag | Description |
311
+ |---|---|
312
+ | `--format json\|table\|csv\|ndjson` | Output format |
313
+ | `--no-color` | Disable ANSI colors (also: `NO_COLOR` env var) |
314
+ | `-q, --quiet` | Suppress stderr progress and warnings |
315
+ | `-v, --version` | Show version |
316
+ | `-h, --help` | Show help |
317
+ | `--help-extra` | Show extended documentation for a command group |
318
+
319
+ ---
320
+
321
+ ## Exit Codes
322
+
323
+ | Code | Meaning |
324
+ |---|---|
325
+ | 0 | Success |
326
+ | 1 | Usage error |
327
+ | 2 | Auth / network error |
328
+ | 3 | Not found |
329
+ | 4 | Permission denied |
330
+ | 5 | Validation error |
331
+ | 6 | Conflict |
332
+ | 10 | Partial success |
333
+
334
+ ---
335
+
336
+ ## As a Library
337
+
338
+ `odoo-cli` is built on `@marcfargas/odoo-client` for all Odoo communication. If you want to automate Odoo programmatically instead of shelling out:
339
+
340
+ ```typescript
341
+ import { createClient } from '@marcfargas/odoo-client';
342
+
343
+ const client = await createClient(); // reads ODOO_* env vars
344
+ const leads = await client.searchRead('crm.lead', [['stage_id.name', '=', 'Won']]);
345
+ await client.mail.postInternalNote('crm.lead', leads[0].id, '<p>Processed by CI</p>');
346
+ ```
347
+
348
+ See the [odoo-toolbox monorepo](../../README.md) for the full ecosystem: RPC client, schema introspection, and Odoo knowledge modules.
349
+
350
+ ---
351
+
352
+ ## License
353
+
354
+ [LGPL-3.0](./LICENSE) — Marc Fargas
package/package.json CHANGED
@@ -1,53 +1,53 @@
1
- {
2
- "name": "@marcfargas/odoo-cli",
3
- "version": "0.1.0",
4
- "description": "CLI for Odoo ERP — records, mail, modules, attendance, timesheets, accounting",
5
- "main": "dist/cli.js",
6
- "bin": {
7
- "odoo": "./dist/cli.js",
8
- "odoo-cli": "./dist/cli.js"
9
- },
10
- "files": [
11
- "dist",
12
- "LICENSE",
13
- "README.md"
14
- ],
15
- "scripts": {
16
- "build": "tsc -b",
17
- "dev": "tsc -b --watch",
18
- "test": "vitest run --config vitest.config.ts",
19
- "test:unit": "vitest run --config vitest.config.ts tests/unit",
20
- "test:e2e": "vitest run tests/e2e",
21
- "test:packaging": "vitest run --config vitest.packaging.config.ts"
22
- },
23
- "keywords": [
24
- "odoo",
25
- "cli",
26
- "erp",
27
- "commander",
28
- "typescript"
29
- ],
30
- "author": "Marc Fargas <marc@marcfargas.com>",
31
- "license": "LGPL-3.0",
32
- "repository": {
33
- "type": "git",
34
- "url": "https://github.com/marcfargas/odoo-toolbox.git",
35
- "directory": "packages/odoo-cli"
36
- },
37
- "dependencies": {
38
- "@marcfargas/odoo-client": "^0.4.1",
39
- "@marcfargas/odoo-introspection": "^0.1.3",
40
- "cli-table3": "^0.6.3",
41
- "commander": "^12.0.0",
42
- "debug": "^4.3.4"
43
- },
44
- "devDependencies": {
45
- "@types/debug": "^4.1.12",
46
- "@types/node": "^20.0.0",
47
- "typescript": "^5.0.0",
48
- "vitest": "^4.0.0"
49
- },
50
- "publishConfig": {
51
- "access": "public"
52
- }
53
- }
1
+ {
2
+ "name": "@marcfargas/odoo-cli",
3
+ "version": "0.2.0",
4
+ "description": "CLI for Odoo ERP — records, mail, modules, attendance, timesheets, accounting",
5
+ "main": "dist/cli.js",
6
+ "bin": {
7
+ "odoo": "./dist/cli.js",
8
+ "odoo-cli": "./dist/cli.js"
9
+ },
10
+ "files": [
11
+ "dist",
12
+ "LICENSE",
13
+ "README.md"
14
+ ],
15
+ "scripts": {
16
+ "build": "tsc -b",
17
+ "dev": "tsc -b --watch",
18
+ "test": "vitest run --config vitest.config.ts",
19
+ "test:unit": "vitest run --config vitest.config.ts tests/unit",
20
+ "test:e2e": "vitest run tests/e2e",
21
+ "test:packaging": "vitest run --config vitest.packaging.config.ts"
22
+ },
23
+ "keywords": [
24
+ "odoo",
25
+ "cli",
26
+ "erp",
27
+ "commander",
28
+ "typescript"
29
+ ],
30
+ "author": "Marc Fargas <marc@marcfargas.com>",
31
+ "license": "LGPL-3.0",
32
+ "repository": {
33
+ "type": "git",
34
+ "url": "https://github.com/marcfargas/odoo-toolbox.git",
35
+ "directory": "packages/odoo-cli"
36
+ },
37
+ "dependencies": {
38
+ "@marcfargas/odoo-client": "^0.4.2",
39
+ "@marcfargas/odoo-introspection": "^0.1.3",
40
+ "cli-table3": "^0.6.3",
41
+ "commander": "^12.0.0",
42
+ "debug": "^4.3.4"
43
+ },
44
+ "devDependencies": {
45
+ "@types/debug": "^4.1.12",
46
+ "@types/node": "^20.0.0",
47
+ "typescript": "^5.0.0",
48
+ "vitest": "^4.0.0"
49
+ },
50
+ "publishConfig": {
51
+ "access": "public"
52
+ }
53
+ }