Skip to main content

odoo-activity

A terminal UI for Odoo instances, on this machine or on a remote host over ssh. One screen: host cpu/mem/uptime, every Odoo instance (systemd --user or supervisor) with its databases nested underneath, and a detail pane for process/log/db inspection.

Installation

uv tool install odoo-activity

Usage

odoo-activity                    # or: oa — this machine
oa openerp@somehost              # a remote host over ssh
oa openerp@somehost -p 10113     # ...on a non-default ssh port

Discovers Odoo instances under systemd --user, supervisor, and odoo.sh (all three are merged), and needs the odoo-db CLI on PATH for the database category tabs. The Config tab additionally needs odoo-config and odoo-addons-path on PATH. See Managers for what each one supports.

The Params tab shows ir_config_parameter secret-looking values unmasked by default — you already have a shell on this host. Pass --no-include-sensitive-information to keep odoo-db's own masking instead.

Key Action
/ move through instances and their nested dbs
s / r start/stop toggle / restart (confirm popup)
[ / ] switch tab in the detail pane
f maximize/minimize the focused pane
p / l / c / t Top / Logs / Config / Toolbox
u / l / j / c / p Users / Locks / Jobs / Crons / Params
K kill -9 the selected process (Top and Processes tabs, confirm popup)
L kill -3 the selected process, then jump to Stacks (Top tab)
D dump stacks of all workers, then jump to Stacks
S copy the instance's odoo shell launch command to the clipboard
e cycle compact/explain/expand/clean (Config tab)
A show all rows, inactive ones included
enter run the selected tool (Toolbox tab, confirm popup) / open a Jobs group / open a row's raw json (db tabs)
escape back out of a Jobs group, or of a row's raw json
/ search
R refresh the active tab now
q quit

Two tabs on each side have no letter shortcut — cycle to them with [/] or click: Processes and Stacks (instance mode), Queries and Modules (database mode).

A asks odoo-db for the rows it filters out by default (its --all flag). Against a host whose odoo-db predates that flag, the tab falls back to the default rows and A says so instead of doing nothing.

Jobs (j)

queue_job's jobs grouped by function and state, numbered, with the oldest creation date and the longest wait/run in each group — which is what a job stuck in started for hours looks like. Enter opens a group as its individual jobs (numbered too, date_created/date_started each, oldest first, capped at 500), escape backs out, and enter on one of those opens its raw json.

Under the table is the tab's action strip — buttons that act on the database rather than on the row under the cursor, so they are not rows themselves. Jobs has one: Requeue jobs puts every started/enqueued job back to pending (after a confirm popup — including jobs a live worker is still running, which will then run again), clearing the dates that go with those states the way queue_job's own set_pending does — what a runner does for its own dead jobs at startup, for when a worker was killed mid-job and nothing else will revisit the row. It's offered even when the table above is empty, and the strip is hidden entirely on a tab that has no actions.

The Processes tab lists the queue_job runner as its own role. Odoo only labels a worker in ps when setproctitle is installed — with it, that label is the whole answer and costs nothing. Without it, the runner is found by its postgres connection instead: application_name names the pid outright from Odoo 16.0 on, and before that (where odoo never set it) the connection is traced by its TCP endpoint, ss or lsof saying which process holds the client port. An instance on a unix socket reports no port and can't be traced that way; if nothing can account for it, the runner just stays under HTTP Worker.

Toolbox (t) offers four tools:

  • Spin a worker up (SIGTTIN) or down (SIGTTOU).
  • Open shell — which copies the launch command instead of signaling, so it needs no confirm.
  • Count sessions under the instance's data dir (walks the filesystem, may be slow).

Remote hosts

The target is any ssh destination — [user@]host or a ~/.ssh/config alias. Only the tools already required locally are needed, but on the remote host. Connections are multiplexed, so the first call opens the session and the rest reuse it.

Everything still refreshes on its own against a remote host, just on a slower tick — host stats and Top every 5s, the instance list every 15s. R refreshes the active tab immediately, plus the instance list and the highlighted instance's databases.

MCP server

oa-mcp [host] exposes the same read-only data as an MCP server, for an agent to work an investigation alongside a human on oa [host] — both looking at the same target. Every tool call is pinned to host (local if omitted); a host/ssh_port argument on a tool call must match the pin or is rejected.

db_query's params output is masked by default, unlike the TUI's: a tool call has no human at the screen, and the plaintext would land in the agent's context. Unmasking is launch-time only, via --include-sensitive-information on the oa-mcp/oa-mcp-multi command line — never a per-call tool argument, so no tool call can turn it on itself.

oa-mcp-multi instead leaves the target per-call, capped by --host-filter (an odoo dbfilter-style regex; unset means unrestricted) and --host-file (which ~/.ssh/config-style file reads aliases from).

Both default to the stdio transport (spawned by the MCP client); add --transport streamable-http --bind-host ... --bind-port ... to run as a network server instead.

Managers

An instance's managersystemd, supervisor, or odoosh — is discovered per instance, not configured, and decides which controller process/log/start-stop-restart lookups route through:

  • systemd — a systemd --user unit, controlled via systemctl --user.
  • supervisor — a supervisorctl status program, controlled via supervisorctl.
  • odoosh — the odoo.sh build a host is running, when odoo-activity itself runs directly on that host (installed via requirements.txt at build time, same as odoo-config/odoo-db). One host is one build, so there's nothing to enumerate — the whole box is "the instance". Start/stop isn't supported (odoo.sh handles sleep/wake on its own); restart goes through odoosh-restart, needed on PATH — which ships pre-installed on odoo.sh hosts.

Config tab modes

e cycles the Config tab through odoo-config's compact/explain/ expand/clean views of the highlighted instance's config file — see odoo-config's CLI docs for what each one shows.

ODOO_ACTIVITY_DB_ROLE overrides the postgres role used to resolve an instance's databases (default: the instance's db_user, falling back to its name).

Architecture

odoo_activity/
├── host.py            # local vs ssh command dispatch
├── probes.py          # all system data: no Textual import, shared by the TUI and MCP server
├── mcp_server.py      # oa-mcp / oa-mcp-multi: probes.py as a read-only MCP tool API
├── panes/detail.py    # ActivityPane: the one stateful rendering widget
├── panes/processes.py   # Processes tab: workers grouped by role
├── panes/stacks.py    # Stacks tab: parsed dumpstacks, busy-first
└── tui.py             # app shell: layout, list, timers, actions
  • host.py — a Host is this machine or an ssh destination. Every probe takes one and runs the same way against either, so nothing above this layer knows whether it is local or remote.
  • probes.py — pure functions, no UI. Every systemctl/supervisorctl/ ps/psql call and /proc read lives here, returning plain dicts/lists so it's testable without spinning up a screen. An instance's databases, logfile and top all resolve from one config: its <workdir>/config/{odoo.conf,server.conf}.
  • mcp_server.py — thin @mcp.tool() wrappers over probes.py, no logic of its own; the same data the TUI shows, for an agent instead of a human (see MCP server).
  • panes/detail.pyActivityPane, the one stateful render widget: a tab strip over a Log/DataTable/Tree, mode-switched by whatever's highlighted (see Modes below) — not a separate popup screen. Delegates the Processes and Stacks tab bodies to panes/processes.py/panes/stacks.py.
  • tui.py — the shell only: compose() layout, the nested instances+dbs ListView, focus/highlight wiring, refresh timers, start/stop/restart. Delegates rendering to ActivityPane, data to probes.py, confirm popups to panes/confirm.py's ConfirmScreen (shared with ActivityPane, which also confirms mutating actions like Toolbox).

Modes

ActivityPane mode-switches on whatever's highlighted in the instances list:

  • Instance mode — an instance row is highlighted. Tabs: Top, Processes, Stacks, Logs, Config, Toolbox.
  • Database mode — one of its nested database rows is highlighted. Tabs: Queries, Users, Locks, Jobs, Crons, Modules, Params.

Both modes share the same tab strip and Log/DataTable widgets (just a _mode flag), and several letter-key shortcuts are reused across them for whichever tab they map to in each (e.g. l is Logs in instance mode, Locks in database mode).

Data sources

  • Instancessystemctl --user list-units and supervisorctl status, merged by name.
  • Databases — each instance's <workdir>/config/{odoo.conf,server.conf} gives a db role (or ODOO_ACTIVITY_DB_ROLE); psql lists the databases owned by that role.
  • Top — the manager gives the instance's master pid (systemctl ... -p MainPID / supervisorctl pid); ps -eo pid,ppid,user,%mem,args is then walked down the ppid tree from there to find every worker.
  • Logs — the same config gives logfile, tailed by reading backward in fixed-size chunks from the end so a multi-GB file costs a few reads, not a full scan.
  • Config — read-only: odoo-config {compact,explain,expand,clean} is run against the instance's config file and its plain-text stdout is shown as-is; the version passed to it comes from odoo-addons-path <workdir> --verbose --format json's version key.
  • Paramsodoo-db params <db> reads ir_config_parameter; / filters rows by key or value. Values are shown as they are: odoo-db masks secret-looking ones (password, token, an enterprise_code, ...) as ******** by default, so the TUI always runs it with --include-sensitive-information.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

odoo_activity-0.16.0.tar.gz (87.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

odoo_activity-0.16.0-py3-none-any.whl (89.1 kB view details)

Uploaded Python 3

File details

Details for the file odoo_activity-0.16.0.tar.gz.

File metadata

  • Download URL: odoo_activity-0.16.0.tar.gz
  • Upload date:
  • Size: 87.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for odoo_activity-0.16.0.tar.gz
Algorithm Hash digest
SHA256 6a4d44f726f6cea837222698cebb013905f25625ecb3a25dcb5f039aa7138802
MD5 13e81e6ec82f263ceecf7f076848ad90
BLAKE2b-256 501f13ec616bb7435024772caf6f2a3de0604d0906ef06a3c03a73c15077faa3

See more details on using hashes here.

Provenance

The following attestation bundles were made for odoo_activity-0.16.0.tar.gz:

Publisher: release.yaml on trobz/odoo-activity

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file odoo_activity-0.16.0-py3-none-any.whl.

File metadata

  • Download URL: odoo_activity-0.16.0-py3-none-any.whl
  • Upload date:
  • Size: 89.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for odoo_activity-0.16.0-py3-none-any.whl
Algorithm Hash digest
SHA256 2140a9386d717c5682df62381108061cd9a94612b010fcded30ea6b8e7069f03
MD5 2d65ab5acd22893485dd687d92fc3af3
BLAKE2b-256 a80ca1acf480d9e63c4854f92be11713d8e6a41f6176f63d8519e46c0dab4f81

See more details on using hashes here.

Provenance

The following attestation bundles were made for odoo_activity-0.16.0-py3-none-any.whl:

Publisher: release.yaml on trobz/odoo-activity

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

0.23.0

2 files

0.22.0

2 files

0.21.0

2 files

0.20.0

2 files

0.19.1

2 files

0.19.0

2 files

0.18.0

2 files

0.17.0

2 files

This release

0.16.0 This release

2 files

0.15.1

2 files

0.15.0

2 files

0.14.0

2 files

0.13.0

2 files

0.12.2

2 files

0.12.1

2 files

0.12.0

2 files

0.11.0

2 files

0.10.0

2 files

0.9.0

2 files

0.8.0

2 files

0.7.0

2 files

0.6.0

2 files

0.5.0

2 files

0.4.0

2 files

0.3.0

2 files

0.2.0

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page