kalup

kalup status

Check the config, and for each target the key, the portal pin, the read scopes and the state file

status tells you whether a project is ready to run. It validates the config, then checks each target: is the key set, does it belong to the pinned portal, and does it hold every read scope the objects in scope need. Run it after init, after changing a key, and first when something fails.

It never writes anything, to the portal or to disk.

Usage

npx kalup status [--target <name>] [--json]

Options

OptionWhat it doesDefault
--target <name>Check one target onlyevery target in the config
--jsonPrint one envelope/1 document to stdout and nothing elseoff

What it does

  1. Validates the config. An invalid config stops status with exit 3 and the first three issues. See kalup validate for the full list.
  2. Checks each target in turn. A problem with one target is one line and one issue. It never stops the checks for the other targets.
    • Key: reads the variable named in credentials.read.env, or HUBSPOT_SERVICE_KEY, from the environment or .env. When it is not set, the target shows the missing variable and the other checks are skipped.
    • Portal pin: asks HubSpot which account the key belongs to, and compares it with the target's portalId. A different account is a mismatch.
    • Protected: reports whether the target is protected. When the config does not say, a STANDARD account counts as protected, and the output says it is the default.
    • Read scopes: sends one list request per scope the objects in scope need: one properties list per standard object, and one schemas list when any custom object is in scope. A 403 means the scope is missing. Any other failure is reported with its code.
    • State: reports whether .kalup/state/<target>.json exists. This version never reads it, so the last apply is always never.
  3. Checks the API pins. When a HubSpot API version that Kalup is pinned to expires within 90 days, it warns with W_PIN_EXPIRES.

Output

kalup 0.1.0
Config: valid (3 objects, 42 properties, 5 groups)
Target sandbox: portal 1111111 matches, SANDBOX, app-eu1.hubspot.com, Europe/Ljubljana, protected: no
  Scopes: crm.schemas.companies.read ok, crm.schemas.deals.read ok, crm.schemas.custom.read ok
  State: none. Last apply: never
Target production: portal 2222222 matches, STANDARD, app-eu1.hubspot.com, Europe/Ljubljana, protected: yes (STANDARD account, default)
  Scopes: crm.schemas.companies.read ok, crm.schemas.deals.read missing (needed for deals), crm.schemas.custom.read ok
  State: none. Last apply: never

A target that did not get past the key or the portal check is one line:

Target production: HUBSPOT_PROD_READ_KEY is not set.
Target staging: unreachable, fetch failed

A scope is ok, missing (needed for ...) after a 403, or failed (<code>) for any other failure, for example failed (E_HTTP) on a 503. With no objects in scope, the line is Scopes: none needed. The issues behind each line go to stderr, one per line, with the fix, for example (fix: Add the scope crm.schemas.deals.read to the key.).

With --json

{
  "format": "envelope/1",
  "ok": false,
  "data": {
    "config": { "valid": true, "counts": { "objects": 3, "properties": 42, "groups": 5 } },
    "targets": [
      {
        "name": "sandbox",
        "portalId": 1111111,
        "keyVariable": "HUBSPOT_SERVICE_KEY",
        "check": "ok",
        "account": {
          "portalId": 1111111,
          "accountType": "SANDBOX",
          "uiDomain": "app-eu1.hubspot.com",
          "timeZone": "Europe/Ljubljana"
        },
        "protected": false,
        "protectedBy": "default",
        "scopes": [
          { "scope": "crm.schemas.companies.read", "ok": true, "neededFor": ["companies"] },
          { "scope": "crm.schemas.custom.read", "ok": true, "neededFor": ["object:subscription"] }
        ],
        "state": "none"
      },
      {
        "name": "production",
        "portalId": 2222222,
        "keyVariable": "HUBSPOT_PROD_READ_KEY",
        "check": "missing-key",
        "reason": "HUBSPOT_PROD_READ_KEY is not set.",
        "scopes": [],
        "state": "none"
      }
    ]
  },
  "issues": [
    {
      "code": "E_MISSING_KEY",
      "message": "HUBSPOT_PROD_READ_KEY is not set.",
      "fix": "Set HUBSPOT_PROD_READ_KEY in the environment or in .env in the project directory."
    }
  ]
}

Per target:

FieldMeaning
keyVariableThe variable the key is read from. Never its value
checkok, missing-key, mismatch (the key belongs to another portal), failed (the portal answered and refused the key or the request) or unreachable (no response at all)
reasonThe first issue's message when check is not ok
accountThe account HubSpot reported. Present once the portal check passed
protected, protectedByWhether the target is protected, and whether the config (config) or the account type (default) decided it. Present once the portal check passed
scopes[]One entry per scope: scope, ok, neededFor (the object name for a standard object, object:<name> addresses for the custom scope), and error with the issue code when the probe failed for a reason other than a missing scope
statepresent when .kalup/state/<target>.json exists, else none

ok is true only when the exit code is 0.

Exit codes

ExitWhen
0Every target checked out. Missing scopes are reported but do not change the exit code
1At least one target has a missing key, a refused key, no response, or a scope probe that failed for a reason other than a missing scope
3The config is invalid, or --target names an undeclared target
4At least one target's key belongs to another portal. A person must check the key and the pinned portalId

Exit 4 wins over exit 1. See Exit codes.

Errors

CodeWhenFix
E_NO_CONFIGNo kalup.config.ts in this directory or aboveRun init first, or run status inside the project
E_UNKNOWN_TARGET--target names a target the config does not declareUse a declared name
E_MISSING_KEYThe variable a target names is not setSet it in the environment or in .env
E_TARGET_PORTAL_MISMATCHThe key belongs to another portal than the pinned portalIdA person checks the key and the pin. Exit 4
E_AUTHHubSpot refused the keyCheck the key is current and belongs to the portal
E_SCOPEThe key lacks a read scopeAdd the scope named in the fix to the key
E_HTTPA request came back with a status status cannot use, such as a 404 or a 503Run again. If it persists, the message names the request
E_UNREACHABLENo response from HubSpot at allCheck the network, then run again
W_RATE_HEADERSHubSpot sent no rate-limit headers for this keyNone needed. Kalup paces itself at a fixed rate
W_PIN_EXPIRESA HubSpot API version Kalup is pinned to expires within 90 daysUpgrade Kalup to a release that pins a newer version

A config error such as E_NOT_DATA stops status with exit 3 before any request.

Examples

Check every target:

npx kalup status

Check only production:

npx kalup status --target production

For agents

  • Run npx kalup status --json first when a command fails for a reason you do not understand.
  • Read data.targets[].check per target. missing-key means the user has to set the variable in keyVariable. Never ask them to paste the key into the chat.
  • A scope with ok: false and no error is missing from the key. Tell the user the scope name in scope. Only the key's creator can add it.
  • Exit 4 means a key belongs to another portal. Stop, and tell the user which target and variable. Do not change portalId to make the check pass.
  • status sends only reads and writes nothing, so it is always safe to run.

On this page