npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@waron97/prbot

v3.9.1

Published

CLI tool for managing PRs, changelogs, and Odoo workflow XML files in the addons repo.

Readme

prbot

CLI tool for managing PRs, changelogs, and Odoo workflow XML files in the addons repo.

Install

Requires Node >= 20.

npm install -g @waron97/prbot

Setup

prbot init

Prompts for all required config values and writes them to ~/.config/prbot/config. Run once, re-run anytime to update config.

Config keys

| Key | Description | | ---------------------- | -------------------------------------------------------- | | ADDONS_PATH | Path to local Odoo addons repo. Unset, empty, or . uses the current directory instead (e.g. a git worktree). Either way the resolved directory must be a git checkout containing config/ — commands refuse to run otherwise. | | KC_URL | Keycloak token endpoint URL | | KC_USER | Keycloak username | | KC_PASSWORD | Keycloak password | | KC_ID | Keycloak client ID | | KC_SECRET | Keycloak client secret | | RIP_URL | RIP API base URL | | TRIDENT_URL | Trident (Odoo) instance URL | | TRIDENT_UID | Trident user ID | | TRIDENT_TOKEN | Trident API token | | TRIDENT_DB | Trident database name | | DEVOPS_TOKEN | Azure DevOps personal access token | | DEVOPS_ORG | Azure DevOps organization | | DEVOPS_PROJECT | Azure DevOps project | | DEVOPS_REPO | Azure DevOps repository name | | AUTOPR_TARGET_BRANCH | Target branch for auto-created PRs (default: 15.0-dev) | | IMPORTEXPORT_URL | ImportExport API base URL |

Commands

prbot pr <module>

Fetches workflow XML for <module> from RIP, writes files into ADDONS_PATH/config/<module>/data/, and commits.

prbot pr config_wf_contestazione

Options:

| Flag | Description | | -------------------- | ------------------------------------------------------------------------- | | -b, --bump <level> | Also bump manifest version after commit. Level: major, minor, patch |

prbot pr config_wf_contestazione -b minor

prbot ver <module>

Bumps the version in __manifest__.py for <module> and commits.

prbot ver config_wf_contestazione --bump patch

prbot changelog <pr>

Writes a changelog entry into CHANGELOG.md for a given PR number. Prompts to select the target section, detects existing indentation, and appends the entry with refs.

prbot changelog 42 -m "Fix invoice state race condition" -t 1234 -t 5678 -j TESTML-1 -j TESTML-2

Options:

| Flag | Description | | ---------------------- | --------------------------------------------- | | -m, --message <text> | Changelog entry message (prompted if omitted) | | -t, --trident <code> | Trident issue code (repeatable) | | -j, --jira <code> | JIRA issue code (repeatable) |

prbot autopr

End-to-end PR automation: creates a branch, pushes it, opens a draft PR on Azure DevOps, appends the PR link to each Trident task's release checklist, writes a changelog entry, commits, and pushes.

# Single Trident task
prbot autopr -t 1234

# Multiple Trident tasks (all get PR link; first with work package drives section matching)
prbot autopr -t 1234 -t 5678

# Multiple Trident + multiple JIRA
prbot autopr -t 1234 -t 5678 -j TESTML-1 -j TESTML-2

# JIRA only — skips all Trident fetch/write operations
prbot autopr -j JIRA-99 --branch my-branch

Options:

| Flag | Description | | ---------------------- | ------------------------------------------------------------------------ | | -t, --trident <id> | Trident task ID (repeatable) | | -j, --jira <code> | JIRA issue code (repeatable) | | -m, --message <text> | Changelog entry message (prompted if omitted) | | -b, --branch <name> | Branch name (default: autopr_<first-task-id> or autopr_<first-jira>) | | -n, --name <text> | PR title (default: Trident task name) |

prbot commit

Interactive commit builder. Prompts for operation type ([IMP], [FIX], etc.), and a message. The destinatin module will be automatically detected. If nothing is staged, shows unstaged files and lets you select which to stage first. Previews the final commit message before confirming.

prbot commit

prbot export workflow

Fetches workflow XML for an interactively selected module from RIP and commits. Prompts to select the module (from ADDONS_PATH/config/ directories) via fuzzy search.

prbot export workflow
prbot export workflow --no-commit

Options:

| Flag | Description | | -------------- | ------------------------------------------------------------- | | --no-commit | Skip the git commit step | | -q, --quiet | Suppress informational output — errors still fail the command | | -s, --silent | Deprecated alias of --quiet; no longer swallows errors |

prbot export pb

Exports a Process Builder process from the ImportExport API and writes the ZIP to ADDONS_PATH/.cloudbuild/pb/B2WA/processes/. Updates the file in place if it already exists, otherwise writes to the all/ subdirectory. Prompts to select the process via fuzzy search.

prbot export pb
prbot export pb --no-commit

Options:

| Flag | Description | | -------------- | ------------------------------------------------------------- | | --no-commit | Skip the git commit step | | -q, --quiet | Suppress informational output — errors still fail the command | | -s, --silent | Deprecated alias of --quiet; no longer swallows errors |

prbot export imperex

Exports a single Imperex record from Odoo via RIP and writes the resulting YAML into ADDONS_PATH/sorgenia_imperex_metadata/migrations/0.0.0/imperex/<model>/. Prompts first for the model (from local folder names), then for the record (fetched from API). Both prompts support fuzzy search.

prbot export imperex
prbot export imperex --no-commit

Options:

| Flag | Description | | -------------- | ------------------------------------------------------------- | | --no-commit | Skip the git commit step | | -q, --quiet | Suppress informational output — errors still fail the command | | -s, --silent | Deprecated alias of --quiet; no longer swallows errors |

prbot export email-templates

Fetches email templates for an interactively selected workflow from RIP and writes them as ADDONS_PATH/config/<module>/data/mail_templates.xml. Prompts first for the module (from ADDONS_PATH/config/ directories), then for the workflow. Both prompts support fuzzy search.

prbot export email-templates
prbot export email-templates --no-commit

Options:

| Flag | Description | | -------------- | ------------------------------------------------------------- | | --no-commit | Skip the git commit step | | -q, --quiet | Suppress informational output — errors still fail the command | | -s, --silent | Deprecated alias of --quiet; no longer swallows errors |

prbot init

Interactive setup: writes ~/.config/prbot/config.

prbot update

Reinstalls prbot from npm — latest by default, or a pinned version.

prbot update           # latest
prbot update 3.4.0     # pin an exact version

agrippa

Syncs Odoo workflow phase Python code, MFA records, process-builder wizards, and long-running processes (LRPs) between the local filesystem and the RIP / Process Builder / Symphony APIs. Tracks changes via checksums and detects conflicts before overwriting.

Credentials are inherited from the global prbot config (~/.config/prbot/config). Override per-workspace in agrippa.yaml.

agrippa init

Creates agrippa.yaml in the current directory. Always writes pyproject.toml with the standard ruff builtins. Optionally writes pyrightconfig.json and copies type stubs into typings/.

agrippa init

agrippa clone

Clones all from_code phases for a selected workflow, a single MFA, a process-builder wizard, or a long-running process (LRP), into the workspace. Writes files to disk and registers them in agrippa.yaml. With no flag, prompts for the object type (MFA / Phase / Process Builder / Long Running Process).

A wizard or LRP is downloaded and decomposed into editable files (structure.yaml, process.yaml, scripts/, pages/, manifest) — LRPs share the same layout minus pages/ (LRPs have no user tasks); see agrippa pb and agrippa-pb.md.

agrippa clone
agrippa clone --phase
agrippa clone --mfa
agrippa clone --phase --id 123 --path my-workflow/
agrippa clone --pb                          # select a wizard
agrippa clone --pb --name ml_review_billing --path my-wizard/
agrippa clone --lrp                         # live search LRPs by name
agrippa clone --lrp --name B2WA_ml_IFS_passive_trigger --path my-lrp/

Options:

| Flag | Description | | --------------- | -------------------------------------------------------------------------- | | --phase | Clone a phase (select a workflow) | | --mfa | Clone an MFA record | | --pb | Clone a process-builder wizard | | --lrp | Clone a long-running process | | --id <id> | Skip selection, clone by ID (phase/mfa) | | --name <name> | Skip selection: document_id (with --pb) or process name (with --lrp) | | --path <path> | Destination path (base dir for phases/wizard/lrp, file for MFA) |

agrippa pull

Fetches remote code for all tracked entries and shows what changed. Classifies each as fast-forward (safe overwrite) or conflict (local edits would be lost). conflict entries are shown but not preselected — you opt in explicitly. Lets you select which to pull.

After pulling, also checks tracked workflows for newly added from_code phases and auto-clones any not yet present locally.

Tracked process-builder wizards and long-running processes are also refreshed from upstream: the local project is re-decomposed from the latest payload (orphan script files pruned; PB wizards also prune orphan pages), with the same fast-forward/conflict classification — a semantic checksum of the recomposed payload (not raw updated_date), canonicalized so cosmetic noise never triggers a false conflict: whitespace-only BPMN text nodes, format-only labelPos, page ordering, and the updated_date/modified_by audit fields Odoo/Symple bump on any server touch are all excluded from the comparison. The current local state is backed up to .backup/<timestamp>/<path>/local.json first.

Plain phase/MFA code is backed up the same way: the current local .py content is written to .backup/<timestamp>/<path> before it's overwritten with the pulled remote code.

agrippa pull
agrippa pull --non-interactive  # no prompts: auto-select fast-forward, fail if any conflict

agrippa push

Pushes local file changes back to RIP (phases/MFAs), the Process Builder API (wizards), and Symphony (long-running processes). Backs up current remote state to .backup/<timestamp>/ before overwriting. Same conflict detection as pull, with the concern inverted. LRP entries are located by name, not id (the Symphony id changes on every save), re-resolving the current id/tenantId immediately before saving.

Pushing a wizard saves it as a draft; publish it so live consumers see the change with --publish (auto) or answer the prompt. Page edits (pages/) are saved independently of the whole-wizard save, mirroring the UI. Pushing an LRP saves the BPMN via Symphony's tabulator PATCH; deploy it (the LRP analog of publish) the same way — --publish/--skip-publish double as auto-deploy/never-deploy for LRPs too.

agrippa push                 # prompts whether to publish/deploy each pushed wizard/LRP
agrippa push --publish       # auto-publish wizards, auto-deploy LRPs
agrippa push --skip-publish  # never publish/deploy (no prompt)
agrippa push --non-interactive  # no prompts: auto-select fast-forward, fail if any conflict;
                                 # publish/deploy defaults to skip unless --publish is also passed

agrippa restore

Restores local workspace files from a .backup/<timestamp>/ snapshot written by an earlier push or pull. Local only — it never touches the remote and never modifies agrippa.yaml/checksum_at_pull; restored content is just local file state, classified against the existing baseline like any other local edit on the next push/pull/diff. No network calls.

Prompts for a snapshot (newest first), then a checkbox of which tracked resources have backup content in it (unchecked by default — this is a deliberate recovery action, not a routine safe one).

What's available to restore, by object type and which command wrote it:

| object_type | push backed up | pull backed up | | ---------------------- | ------------------------------------- | ------------------------------------ | | phase / mfa | remote code (about to be overwritten) | local code (about to be overwritten) | | process_builder | full remote payload (upstream.json) | full local payload (local.json) | | long_running_process | remote BPMN only (upstream.xml) | full local payload (local.json) |

agrippa restore
agrippa restore --timestamp 2026-08-05_14-30-00Z   # skip the snapshot picker

Options:

| Flag | Description | | ------------------ | ----------------------------------------------------------- | | --timestamp <ts> | Backup snapshot to restore from (skips the snapshot picker) |

agrippa diff [target]

Shows a diff between local files and remote code. [target] optionally narrows it to a single file, a workflow folder, a cloned project directory, or a document_id/name; omit it for the whole workspace.

For process-builder wizards and long-running processes, diffs the whole project tree against what the workspace would look like if the project were decomposed fresh from upstream right now (.backup/ and preview.svg are excluded as local-only artifacts).

agrippa diff
agrippa diff my-workflow/some-phase.py
agrippa diff ml_review_billing      # a cloned wizard's directory
agrippa diff B2WA_M2C_passthrough   # a cloned LRP, by directory or name

agrippa init-phase

Selects a workflow and any phase, then pushes a default code scaffold to that phase on RIP. Sets set_result_automatically to from_code, generates result variable constants from the phase's allowed results, and creates the corresponding result.code.configurator records.

agrippa init-phase

agrippa repair

Removes entries from agrippa.yaml whose local files no longer exist on disk.

agrippa repair

agrippa pb

Local editing helpers for a cloned process-builder wizard or long-running process (no network — they edit the decomposed files in place; both share the same decomposed layout and BPMN engine). Each operates on one wizard/LRP, resolved by --pb <document_id_or_name> (name for LRPs, since they have no document_id), single-entry auto-select, or a fuzzy prompt.

These commands exist mainly so an AI agent can add/remove/connect blocks without hand-editing the multi-thousand-line structure.yaml. Human users typically edit blocks in the UI instead. Full agent-facing guide (also usable as a workspace CLAUDE.md): agrippa-pb.md.

Newly added blocks get placeholder geometry. pb format re-lays-out the whole diagram (discarding any hand-tuned layout), so running it is a deliberate human decision — the alternative is positioning the new blocks by hand in the UI. Agents are expected to make structural edits but not to run format or to pull/push; a human reviews and syncs.

| Command | Purpose | | --------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- | | pb format | Re-lay-out the entire diagram (elkjs, left→right); overwrites existing layout | | pb add | Add a node (--type, --name, --parent); scaffolds script/page files | | pb rm | Remove a node (--id), its edges, and its script/page files | | pb connect | Add a flow (--from, --to, --condition, --default); enforces the gateway rule | | pb disconnect | Remove a flow (--id, or --from/--to); clears the source gateway's default if it pointed at that flow | | pb lint | Check the structural rules: gateway defaults/conditions, branch names, incoming-flow limits, and defaults pointing at flows that no longer exist | | pb ls | List nodes and edges with their ids (discover targets without reading the YAML) | | pb preview | Render the diagram to an SVG (--out) for a quick visual check |

agrippa pb ls --pb ml_review_billing
agrippa pb add --type scriptTask --name "Check pod" --pb ml_review_billing
agrippa pb connect --from ScriptTask_x --to ExclusiveGateway_y --pb ml_review_billing
agrippa pb format --pb ml_review_billing

agrippa pb ls --pb B2WA_ml_IFS_passive_trigger        # LRP, resolved by name
agrippa pb add --type serviceTask --name "Call SAP" --pb B2WA_ml_IFS_passive_trigger

userTask (pages) can't be added to an LRP project — LRPs never have user tasks.