@gorules/cli
v0.3.3
Published
Command-line tool for the GoRules BRMS platform
Readme
@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/cliOr run directly with npx (e.g. mcp start):
npx @gorules/cli mcp startPulling 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/ --recursiveTargets
| 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 ./rulesWith --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/ --recursiveA 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 COPYScheduled 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 ;;
esacExit 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/[email protected] pull --project pricing --target env:production # x-release-please-versionGitHub 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/[email protected] # 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: DeployGORULES_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 startThis 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
- Run
gorules mcp start - Open the GoRules editor and click Connect MCP
- 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-decisionThese 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