Skip to content

Repository files navigation

@gorules/cli

Command-line tool for GoRules — a business rules management system (BRMS) for decision tables, decision graphs, and expressions.

Installation

npm install -g @gorules/cli

Or run directly with npx (e.g. mcp start):

npx @gorules/cli mcp start

Pulling rules into a pipeline

gorules pull resolves a target in BRMS and downloads the matching rules artifact. It is the building block for shipping rules from BRMS into your own infrastructure: a CI job pulls the artifact and uploads it wherever your runtime reads it from.

export GORULES_URL=https://acme.us1.gorules.io
export GORULES_TOKEN=...            # project access token, read scope is enough

gorules pull --project pricing --target env:production --out ./dist
aws s3 cp ./dist/ s3://my-bucket/rules/live/ --recursive

Targets

Target Resolves to
main (default) latest commit on the default branch
branch:<branchId> latest commit on that branch
commit:<commitId> that exact commit, pinned
release:<version> that release, by semantic version or id
env:<key> whichever release is deployed to that environment

Options

Flag Env Description
-p, --project GORULES_PROJECT Project key or id
-t, --target GORULES_TARGET Target to resolve (default main)
-o, --out Output directory (default .)
--unpack Extract the archive instead of writing it
--delete With --unpack: delete files not in the artifact so the directory mirrors the target exactly
--name Output file name (zip) or sub-directory name (dir); defaults to the project key with no extension
--current Release or commit id you already hold; exits 3 when unchanged
-u, --url GORULES_URL BRMS URL
--token GORULES_TOKEN Access token
--json Print the result as JSON on stdout

Naming the output

The default writes <project-key> with no .zip suffix, because the agent's S3, GCS and Azure Blob providers use the object name verbatim as the project key: upload pricing.zip and the agent serves a project literally called pricing.zip.

The agent's local zip provider is the opposite -- it reads <root>/<project>.zip and strips the suffix itself -- so that destination needs it back:

gorules pull --project pricing --name pricing.zip --out ./rules

With --unpack, --name is the sub-directory to extract into (default: the project key, which is the layout the agent's filesystem provider expects). Pass --name . to extract straight into --out, which is what you want when baking rules into a container image.

Extraction behaves like aws s3 sync: byte-identical files are left untouched, changed files are written atomically (temp file + rename, so a concurrent reader never sees a partial write), and files the artifact does not carry are preserved. Add --delete for s3 sync --delete semantics: the directory mirrors the target exactly, so rules deleted in BRMS are deleted on disk too. As a guard against wiping a directory it does not own, --delete refuses a non-empty destination that has no .config/project.json from a previous pull, and deletions only run after every new file has been written.

Examples

Object storage that the agent watches -- one archive per project, no extension:

gorules pull --project pricing --target env:production --out ./dist
aws s3 cp ./dist/ s3://my-bucket/rules/live/ --recursive

A volume the agent reads with its filesystem provider -- unpacked, one directory per project:

gorules pull --project pricing --target env:production --out /srv/rules --unpack
# /srv/rules/pricing/...

Baked into a container image, pinned to an exact release so the build is reproducible:

gorules pull --project pricing --target release:1.4.2 --out ./rules --unpack --name .
# ./rules/*.json + ./rules/.config/project.json, ready for COPY

Scheduled job that does nothing when production has not moved:

gorules pull --project pricing --target env:production --current "$LAST_RELEASE_ID" --out ./dist
case $? in
  0) aws s3 cp ./dist/ s3://my-bucket/rules/live/ --recursive ;;
  3) echo "unchanged" ;;
  *) exit 1 ;;
esac

Exit codes

Code Meaning
0 Artifact downloaded
1 Error
2 Usage error (missing or invalid arguments)
3 Nothing to do (--current matched what is deployed)
4 No release is deployed to the target

Pin the version in a pipeline rather than tracking latest:

npx @gorules/cli@0.3.3 pull --project pricing --target env:production # x-release-please-version

GitHub Actions

Composite actions live under actions/, in this repository, so the tag you pin is the CLI version you get.

on:
  workflow_dispatch:
    inputs:
      payload:
        description: Set by BRMS when a webhook triggers the run; the action picks it up automatically
        required: false
        type: string

jobs:
  rules:
    runs-on: ubuntu-latest
    steps:
      - uses: gorules/cli/actions/pull@cli-v0.3.3 # x-release-please-version
        id: rules
        with:
          url: https://acme.us1.gorules.io
          token: ${{ secrets.GORULES_TOKEN }}
          # project and target normally arrive in the BRMS payload; set them
          # only for runs that have none (manual without payload, schedules)
          out: ./dist

      - name: Deploy
        env:
          PROJECT: ${{ steps.rules.outputs.project }}
        run: aws s3 cp "./dist/$PROJECT" "s3://my-bucket/rules/$PROJECT"
Input Required Description
url yes BRMS URL
token yes Access token; pass a secret
project yes* Project key or id; optional when payload is set
target Target to resolve (default main)
out Output directory (default .)
name Output file or sub-directory name
unpack true to extract the archive
delete With unpack, mirror the target exactly (delete stale files)
current Release or commit id already held
payload BRMS event payload; auto-detected from workflow_dispatch, set only to override
cli-version Version of @gorules/cli to run
Output Description
project / target What was pulled, payload-aware
changed false when current still matched, so nothing was downloaded
release / version / commit What the target resolved to
sha256 Checksum of the downloaded artifact
files JSON array of paths written

The token is passed to the CLI as an environment variable rather than an argument, and masked in the log. changed exists so a scheduled workflow can skip the upload when production has not moved.

GitLab CI

templates/gitlab-ci-pull.yml defines a hidden job you extend:

include:
  - remote: 'https://raw.githubusercontent.com/gorules/cli/cli-v0.3.3/templates/gitlab-ci-pull.yml' # x-release-please-version

pull:rules:
  extends: .gorules-pull
  # project and target normally arrive in the BRMS payload (GRL_PAYLOAD);
  # set GORULES_PROJECT / GORULES_TARGET only for runs that have none

publish:rules:
  needs: ['pull:rules']
  script:
    # dotenv variables are not visible in rules: (evaluated before jobs run) -
    # gate in script when using scheduled pulls with GORULES_CURRENT
    - aws s3 cp "dist/$RULES_PROJECT" "s3://my-bucket/rules/$RULES_PROJECT"

GORULES_URL and GORULES_TOKEN are CI/CD variables; mask and protect the token. GitLab puts them in the environment automatically, so nothing else is needed to wire them up. Optional job variables: GORULES_OUT (default dist), GORULES_NAME, GORULES_CURRENT, GORULES_UNPACK and GORULES_DELETE (both 'false' by default), and GORULES_CLI_VERSION.

The job publishes RULES_CHANGED, RULES_PROJECT, RULES_TARGET, RULES_VERSION, RULES_RELEASE and RULES_SHA256 as a dotenv report, so later jobs read them as ordinary variables — a deploy job can route on the target (e.g. per-environment buckets) without parsing anything.

Azure Pipelines

templates/azure-pipelines-pull.yml is a steps template: it pulls the artifact and sets result variables (rulesChanged, rulesProject, rulesTarget, rulesVersion, rulesRelease, rulesSha256), and you append your own publish step in the same job:

resources:
  repositories:
    - repository: gorules
      type: github
      name: gorules/cli
      ref: refs/tags/cli-v0.3.3 # x-release-please-version
      endpoint: <your GitHub service connection>

jobs:
  - job: deploy_rules
    pool:
      vmImage: ubuntu-latest
    steps:
      - template: templates/azure-pipelines-pull.yml@gorules
        parameters:
          url: https://acme.us1.gorules.io
          # project and target normally arrive in the BRMS payload (GRL_PAYLOAD)

      - script: aws s3 cp "$(Build.ArtifactStagingDirectory)/rules/$(rulesProject)" "s3://my-bucket/rules/$(rulesProject)"
        displayName: Deploy

GORULES_TOKEN must exist as a secret pipeline variable or in a linked variable group. Azure DevOps does not map secret variables into the environment automatically, which the template handles by declaring it explicitly under env:.

The job sets rulesChanged and rulesVersion as pipeline variables for later stages to read.

Triggered by BRMS

All three templates read GRL_PAYLOAD when it is present, which is what BRMS sends when a webhook triggers the pipeline. The project and target then come from the event rather than from static configuration, so one pipeline handles every project and environment:

System How the payload arrives
GitHub Actions inputs.payload on workflow_dispatch
GitLab CI GRL_PAYLOAD pipeline variable
Azure Pipelines GRL_PAYLOAD run variable

Without it, the configured GORULES_PROJECT and GORULES_TARGET are used, so the same file also works for a manual or scheduled run.

MCP Bridge

2 The CLI includes an MCP (Model Context Protocol) bridge that connects AI tools like Claude, Cursor, and Windsurf to the GoRules decision graph editor.

Quick Start

gorules mcp start

This starts a local server on localhost:41919 that:

  • Exposes an MCP endpoint (/mcp) for AI tool integration
  • Connects to the GoRules editor via WebSocket
  • Provides REST endpoints for evaluating decisions and fetching files

Options

Flag Description Default
-p, --port Server port 41919
-h, --host Server host localhost
-u, --url GoRules server URL
--open Open browser on start false

Connecting

  1. Run gorules mcp start
  2. Open the GoRules editor and click Connect MCP
  3. Enter the connection token displayed in your terminal

REST Endpoints

The bridge exposes REST endpoints for local development:

Evaluate a decision graph:

curl -X POST http://localhost:41919/evaluate/my-decision \
  -H "Content-Type: application/json" \
  -d '{"context": {"customer": {"tier": "premium"}, "orderTotal": 150}}'

Retrieve a decision file:

curl http://localhost:41919/file/my-decision

These endpoints can also be used as a loader for ZenEngine:

const engine = new ZenEngine({
  loader: async (key) => {
    const res = await fetch(`http://localhost:41919/file/${key}`);
    return res.json();
  },
});

AI Tool Configuration

Add the MCP server to your AI tool's configuration:

Claude Desktop / Claude Code:

{
  "mcpServers": {
    "gorules": {
      "command": "gorules",
      "args": ["mcp", "start"]
    }
  }
}

Development

pnpm install
pnpm dev          # Build and run
pnpm build        # Production build
pnpm lint         # Lint
pnpm format:fix   # Format

License

MIT

About

Command-line tool for the GoRules BRMS platform

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages