> For the complete documentation index, see [llms.txt](https://govplane.gitbook.io/docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://govplane.gitbook.io/docs/documentation/cli/configuring-the-cli-toolkit.md).

# Configuring the CLI Toolkit

The toolkit reads the **same** `govplane.config.json` the CLI does, in the same working folder. It adds blocks the CLI ignores, so one file serves both.

```json
{
  "schemaVersion": 1,
  "draft":  { "path": "policy-drafts.json" },
  "bundle": { "path": "policy-bundle.json" },

  "build": {
    "env": "prod",
    "outputDirectory": "dist",
    "signed": true,
    "validateParity": true,
    "bundleVersionStrategy": "increment",
    "scope":   { "orgId": "org_demo", "projectId": "proj_demo" },
    "signing": {
      "algorithm": "ECDSA_SHA_256",
      "keyId": "release-2026-08",
      "ecdsaPrivateKeyPath": "keys/signing.pem"
    }
  },

  "sign": {
    "signing": {
      "algorithm": "HMAC_SHA256",
      "keyId": "ci-key-01",
      "hmacSecretEnv": "GOVPLANE_HMAC_SECRET"
    }
  }
}
```

See [Configuring the CLI](broken://pages/d08084da482deec8c78361607c91fe53266d1adf) for `draft`, `bundle`, `signature` and `limits`.

## `build`

| Field                             | Default        | Purpose                                                           |
| --------------------------------- | -------------- | ----------------------------------------------------------------- |
| `env`                             | `prod`         | Environment recorded in the bundle                                |
| `outputDirectory`                 | working folder | Where the bundle is written                                       |
| `signed`                          | `false`        | Sign as part of the build                                         |
| `validateParity`                  | `true`         | Validate the compiled bundle against the runtime rules            |
| `bundleVersionStrategy`           | `increment`    | Only `increment` is implemented; any other value falls back to it |
| `scope.orgId` / `scope.projectId` | —              | Written into the bundle                                           |

Command-line flags win over configuration: `--env`, `--org-id`, `--project-id`, `--signed`.

{% hint style="info" %}
`orgId` and `projectId` are **optional** for a bundle you evaluate locally — the SDK does not read them, and `govplane validate` accepts a bundle without them. Set them when the bundle is destined for Govplane Cloud, which addresses bundles by scope.
{% endhint %}

## `sign`

`build.signing` and `sign.signing` are **separate blocks on purpose**, so a project can build unsigned in development and sign with a different key in a release pipeline.

| Field                 | Purpose                                      |
| --------------------- | -------------------------------------------- |
| `algorithm`           | `ECDSA_SHA_256` or `HMAC_SHA256`             |
| `keyId`               | Identifier recorded in the signature         |
| `hmacSecretEnv`       | Environment variable holding the HMAC secret |
| `ecdsaPrivateKeyPath` | ECDSA private key, PEM                       |

Verification — used by `simulate` to check a bundle before evaluating it — reads **both** blocks, with `sign.signing` winning where they overlap. A project that only ever builds signed still has key material pinned, and reading `sign.signing` alone would find nothing and skip verification silently.

## Signing keys

| Algorithm       | Key material           | Use it for                                            |
| --------------- | ---------------------- | ----------------------------------------------------- |
| `ECDSA_SHA_256` | P-256 private key, PEM | Anything you distribute — the public half verifies it |
| `HMAC_SHA256`   | 64 hex characters      | Bundles that never leave your own systems             |

{% tabs %}
{% tab title="ECDSA" %}

```bash
govplane build --signed \
  --signing-algorithm ECDSA_SHA_256 \
  --ecdsa-private-key ./keys/signing.pem
```

{% endtab %}

{% tab title="HMAC" %}

```bash
govplane build --signed \
  --signing-algorithm HMAC_SHA256 \
  --hmac-secret-env GOVPLANE_HMAC_SECRET
```

{% endtab %}
{% endtabs %}

{% hint style="danger" %}
Prefer `--hmac-secret-env` over `--hmac-secret`. A secret passed as an argument lands in your shell history, in `ps` output, and in CI logs that echo the command.
{% endhint %}

Generate a P-256 key pair:

```bash
openssl ecparam -genkey -name prime256v1 -noout -out keys/signing.pem
openssl ec -in keys/signing.pem -pubout -out keys/signing.pub.pem
```

The **public** half is what the SDK needs, and it is not a secret — commit it, bake it into the image, ship it in a ConfigMap. Only the private half needs protecting, and it never leaves the build machine.

Choosing between the two, and what a signature does and does not prove: [Configuring the SDK](/docs/documentation/sdk-for-javascript-node.js/configuring-the-js-sdk.md).

## Environment variables

The toolkit reads everything the CLI does, plus:

| Variable                      | Purpose                                                                         |
| ----------------------------- | ------------------------------------------------------------------------------- |
| `GOVPLANE_LICENSE`            | Licence contents, inline — for CI                                               |
| `GOVPLANE_LICENSE_FILE`       | Path to a licence file                                                          |
| `GOVPLANE_HMAC_SECRET`        | Conventional name for the HMAC secret (any name works with `--hmac-secret-env`) |
| `GOVPLANE_API_URL`            | Activation endpoint — for staging and local development only                    |
| `GOVPLANE_LICENSE_PUBLIC_KEY` | Override the licence verification key — for development against a stub          |

The last two exist so the activation flow can be run against a local stub server. Neither is needed in normal use.

## A CI configuration

```yaml
jobs:
  policy:
    runs-on: ubuntu-latest
    env:
      GOVPLANE_HOME: ${{ github.workspace }}/.govplane
      GOVPLANE_LICENSE: ${{ secrets.GOVPLANE_LICENSE }}
      GOVPLANE_HMAC_SECRET: ${{ secrets.GOVPLANE_HMAC_SECRET }}
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with: { node-version: '22' }
      - run: npm install --global @govplane/cli @govplane/cli-toolkit

      - run: govplane analyze --source ./src --check -w ./governance
      - run: govplane validate --strict -w ./governance
      - run: govplane build --signed --hmac-secret-env GOVPLANE_HMAC_SECRET -w ./governance
      - run: govplane simulate --suite ./governance/simulations/auth.json -w ./governance
```

Setting `GOVPLANE_HOME` inside the workspace keeps Govplane state out of the runner's home directory.

{% hint style="warning" %}
A per-run `GOVPLANE_HOME` also means a per-run grace clock. Supply `GOVPLANE_LICENSE` rather than relying on the 30-day grace period, or the pipeline will keep reporting day 1 forever and never actually be activated.
{% endhint %}

## Next

* [CLI Toolkit Commands](/docs/documentation/cli/cli-toolkit-commands.md)
* [A Practical Example, Start to End](/docs/documentation/cli/practical-example-from-start-to-end.md)

## More detail

* [`build` reference](https://github.com/Govplane/govplane-cli-toolkit/blob/main/docs/commands/build.md) · [`sign` reference](https://github.com/Govplane/govplane-cli-toolkit/blob/main/docs/commands/sign.md)
* [CI and automation](https://github.com/Govplane/govplane-cli-toolkit/blob/main/docs/automation.md)
* [Toolkit architecture](https://github.com/Govplane/govplane-cli-toolkit/blob/main/docs/architecture.md)


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://govplane.gitbook.io/docs/documentation/cli/configuring-the-cli-toolkit.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
