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

@rglabs/butterfly

v3.3.1

Published

CLI tool to download resources from the Butterfly platform

Readme

Butterfly CLI

CLI tool for downloading and synchronizing resources from the Butterfly platform.

Installation

# Global installation
npm install -g @rglabs/butterfly

# Or use with npx (no installation required)
npx @rglabs/butterfly <command>

Quick Start

# 1. One-time: initialize git (enables IDE merge UI on conflicts)
butterfly init

# 2. Configure authentication
butterfly setup

# 3. Pull resources from the server
butterfly pull

# 4. Push your local changes back
butterfly push <path>

# 5. Check sync state at any time
butterfly status

# When status shows `divergent`, do a 3-way merge:
butterfly diff -t reports -n <name> --apply merge

pull / push are guarded: they refuse to silently overwrite changes made by teammates between your last sync and now. The guard is powered by the server-side object_logs audit table — see Sync Guard below. The legacy download / upload commands still work and use the same guard.

On divergent, diff --apply merge does a git-style 3-way merge and stages conflicted files in the git index so your IDE (PhpStorm/IntelliJ/VSCode) opens its built-in merge resolver automatically. butterfly init enables this by ensuring the checkout is a git repo.

Commands

butterfly setup

Configure authentication for the Butterfly platform.

butterfly setup

You'll be prompted to enter:

  • Endpoint: Your Butterfly platform URL (e.g., https://app.example.com)
  • Email: Your login email
  • Password: Your password

Configuration is saved to .butterfly/config.json.


butterfly pull / butterfly push / butterfly status

Team-safe sync commands. They use the same logic as download / upload but gate every operation through a sync guard backed by object_logs.

# Fetch remote changes — refuses to overwrite local edits
butterfly pull
butterfly pull -t reports
butterfly pull --force            # overwrite local edits

# Push local changes — refuses to overwrite remote changes
butterfly push butterfly-resources/reports/foo
butterfly push <path> --force     # overwrite remote (clobbers teammate work)

# Inspect: shows clean / local-only / remote-only / divergent / untracked
butterfly status

When a push is blocked, the CLI lists each divergent resource (with +N remote logs summarizing how many writes happened on the server since your last sync) and points you to butterfly diff for an interactive field-by-field review.

See Sync Guard for internals.


butterfly download

Download resources from the Butterfly platform. Same as pull (sync guard is active on both — pull is the recommended alias).

# Download all resource types
butterfly download

# Download specific resource type
butterfly download -t objects
butterfly download -t reports
butterfly download -t bfy_workflows
butterfly download -t bfy_ai_tasks
butterfly download -t bfy_state_machines
butterfly download -t pages
butterfly download -t bfy_cronjobs
butterfly download -t cms_email_templates
butterfly download -t cms_email_layouts
butterfly download -t webservices
butterfly download -t translations
butterfly download -t static_files

# Download specific resource by name
butterfly download -t objects -n users

# Custom output directory
butterfly download -o ./my-resources

# Clean existing files before downloading
butterfly download --cleanup

Options: | Option | Description | |--------|-------------| | -t, --type <type> | Resource type to download | | -n, --name <name> | Specific resource name | | -o, --output <path> | Output directory (default: ./butterfly-resources) | | --cleanup | Clean existing contents before downloading | | --force | Bypass the sync guard and overwrite locally-edited files |


butterfly upload

Upload specific files or folders to the platform. Same as push (sync guard is active on both — push is the recommended alias).

# Upload a single file
butterfly upload butterfly-resources/objects/app/users/name/spec.json

# Upload a folder
butterfly upload butterfly-resources/objects/app/users

# Upload multiple targets
butterfly upload file1.json folder1 file2.json

# Upload a static file (any extension under static_files/)
butterfly upload butterfly-resources/static_files/test/aa.html

# Bypass the sync guard (DANGEROUS — clobbers remote changes)
butterfly upload reports/foo --force

Options: | Option | Description | |--------|-------------| | --force | Bypass the sync guard and overwrite remote changes |


Sync Guard

pull / push / download / upload are protected by a sync guard that uses the server-side object_logs audit table to detect concurrent edits between teammates and prevent silent overwrites.

How it works

  1. Manifest: .butterfly/sync-manifest.json (auto-added to .gitignore, per-checkout). Each entry stores last_log_id, local_hash (SHA-256 of the canonical resource payload, stripping transient fields like updated_at), and last_synced_at.

  2. On pull / download:

    • Hashes every tracked file and compares to its checkpoint.
    • If any are dirty → blocks before overwriting, lists them, points to git stash / --force.
    • On success: walks the output directory, resolves every (table, id) pair it can identify (objects, specs, reports, queries, state machines, workflows, cronjobs, email templates, pages, webservices), and stamps a fresh checkpoint with the current max(object_logs.id) for that record.
  3. On push / upload:

    • Resolves each target file → (table, id) → queries object_logs for rows with id > checkpoint.last_log_id for that record.
    • Local-only changes: push proceeds.
    • Remote-only or divergent: push is blocked. Output shows +N remote log(s) so you know how much movement happened on the server.
    • On success: re-fetches the new max(object_logs.id) and updates the checkpoint forward.
  4. --force on either command bypasses the guard but still updates the manifest after the operation.

  5. butterfly status lists every checkpoint with its current state. Exit code 1 if anything is divergent — useful for CI.

Conflict workflow

$ butterfly push butterfly-resources/reports/foo
Sync check: 0 clean, 0 local-only, 0 remote-only, 1 divergent, 0 untracked
  ⚠  DIVERGENT  cms_reports:11 (foo)  (+1 remote log)

Push blocked — remote has changes since your last sync.
• cms_reports:11 (foo) [divergent]

Run `butterfly diff` to review, pull and resolve, or re-run with --force to overwrite.

The guard is client-side — no Butterfly backend changes are required. It queries object_logs via the existing /admin/ajax/cms_object/get endpoint and filters by id > last_log_id in memory.

Static files: files under butterfly-resources/static_files/ are mirrored from the static_files object. Downloads materialize each record as a file at static_files/<custom_seo> (sub-paths become folders) with file_content as the body. Uploads reverse the mapping — the path relative to static_files/ becomes custom_seo, the file body becomes file_content, and an existing record with that custom_seo is updated (or a new one is created). Any file extension is accepted under this tree.


butterfly add

Create new resources via API and download them locally.

# Create a new workflow
butterfly add -t workflow --title "My Workflow" --system-name my_workflow

# Add a node to a workflow
butterfly add -t workflow-node -w my_workflow --title "Process Data" --node-type CustomScript --node-group Code

# Add a node and connect it to an existing node
butterfly add -t workflow-node -w my_workflow --title "Send Email" --node-type Email --node-group Output --connect-from 123

# Create a connection between nodes
butterfly add -t workflow-connection -w my_workflow --from 123 --to 456

Options: | Option | Description | |--------|-------------| | -t, --type <type> | Resource type (workflow, workflow-node, workflow-connection) | | -w, --workflow <name> | Workflow name or ID | | -v, --version <number> | Version number (defaults to latest) | | --title <title> | Title/name of the resource | | --node-type <type> | Node identifier (e.g., CustomScript, WebHook, RESTAPI) | | --node-group <group> | Node group (e.g., Code, Trigger, Connector, Output) | | --connect-from <spec> | Connect from existing node to new node | | --connect-to <spec> | Connect from new node to existing node |


butterfly workflow-info

Get information about available workflow node types.

# List all node groups
butterfly workflow-info --groups

# List nodes in a specific group
butterfly workflow-info --nodes Database

# Get details for a specific node
butterfly workflow-info --details RESTAPI --group Connector

butterfly diff

Compare local resources with remote server and apply changes interactively.

# Compare all objects
butterfly diff -t objects

# Compare specific object
butterfly diff -t objects -n users

# Compare reports
butterfly diff -t reports -n my_report

Options: | Option | Description | |--------|-------------| | -t, --type <type> | Resource type to compare (objects, reports) | | -n, --name <name> | Specific resource name to compare | | -o, --output <path> | Base path (default: ./butterfly-resources) |


butterfly record

Perform CRUD operations on any Butterfly table.

# Get a record by ID
butterfly record get users --id 123

# Get records by column filter
butterfly record get users --column email --value "[email protected]"

# Wildcard search
butterfly record get users --column name --value "john*"

# Add a new record
butterfly record add users --data '{"name": "John", "email": "[email protected]"}'

# Edit a record
butterfly record edit users --id 123 --data '{"name": "Jane"}'

# Delete a record (with confirmation)
butterfly record delete users --id 123

# Skip preview and auto-confirm
butterfly record edit users --id 123 --data '{"status": "active"}' --no-preview -y

Options: | Option | Description | |--------|-------------| | --id <id> | Record ID | | --column <column> | Filter column(s) for get | | --value <value> | Filter value (use * for wildcard) | | --columns <cols> | Select specific columns to return | | --data <json> | JSON data for the operation | | --file <path> | Path to JSON file with data | | --db-alias <alias> | Database alias (default: default) | | --no-preview | Skip preview | | -y, --yes | Auto-confirm without prompting |


butterfly code

Execute Twig code on the server.

# Execute inline code
butterfly code -c "{{ db().table('users').count() }}"

# Execute from file
butterfly code -f query.bfy

# Get only variables
butterfly code -c "{% set users = db().table('users').get() %}" --vars

# Get raw output
butterfly code -c "{{ 'Hello World' }}" --output-only --raw

Options: | Option | Description | |--------|-------------| | -c, --code <code> | Twig code to execute (inline) | | -f, --file <path> | Path to file containing Twig code | | -o, --output <path> | Save output to file | | --vars | Output only the vars object | | --output-only | Output only the output field | | --raw | Output raw string (no JSON formatting) |


butterfly layout

Update object page layout (tab and field ordering).

# Update layout from file
butterfly layout -f layout.json

# Update layout inline
butterfly layout -d '{"object_id": 123, "tabs": [...]}'

butterfly translate

Manage translations for multi-language support.

# List languages with translation stats
butterfly translate languages

# Get untranslated texts for a language
butterfly translate get-untranslated --lang tr

# Add a single translation
butterfly translate add --lang tr --source "Welcome" --text "Hoş geldiniz"

# Bulk import from CSV file (tab-delimited)
butterfly translate bulk --lang tr --file translations.csv

Options: | Option | Description | |--------|-------------| | --lang <iso_code> | Language ISO code (e.g., tr, de, en) | | --source <text> | Source text to translate | | --text <translation> | Translated text | | -f, --file <path> | CSV file for bulk operations | | --format <format> | Output format: json or table | | --limit <count> | Limit number of results |

Directory Structure

After downloading, resources are organized as follows:

butterfly-resources/
├── objects/
│   ├── butterfly/              # Core CMS objects
│   └── app/                    # Application objects
│       └── [table_name]/
│           ├── object.json
│           ├── listing_query.bfy
│           └── [field_name]/
│               ├── spec.json
│               └── [code_files]
├── reports/
│   └── [report-alias]/
│       ├── report.json
│       ├── main_query.bfy
│       ├── queries/
│       └── specs/
├── bfy_workflows/
│   └── [workflow_name]/
│       ├── workflow.json
│       └── v1/
│           ├── version.json
│           ├── connections.json
│           └── nodes/
├── bfy_ai_tasks/
├── bfy_state_machines/
├── pages/
├── bfy_cronjobs/
├── cms_email_templates/
├── cms_email_layouts/
├── webservices/
│   └── [custom_seo]/
│       ├── webservice.json
│       └── queries/
└── static_files/
    └── [custom_seo_path]    # e.g. test/aa.html — file IS the resource

Field Type Code Files

The CLI automatically extracts code from field specs:

| Field Type | Parameter | Output File | |------------|-----------|-------------| | calculated | val_1 | code.bfy | | custom | val_1 | template_code.bfy | | custom | val_2 | processing_code.bfy | | filter | val_3 | filter_code.bfy | | nested | val_1 | configuration.yaml | | js_code | - | code.js | | css_code | - | style.css |

Requirements

  • Node.js >= 16.0.0

License

ISC