For the complete documentation index, see llms.txt. This page is also available as Markdown.

Run the Integration Locally

Run your Pandium TypeScript integration locally with the Pandium CLI, which supplies your tenant's secrets, configs, and context, then trim the starter code down to a clean starting point.

Pandium gives your integration its secrets, tenant settings, and context when it runs on Pandium. During local development pandium local run fetches those same values from your tenant and runs your integration with them, so your code behaves the same way in both places.

You can read more about the environmental variables Pandium gives your integration during run time.

  1. Run pandium local build && pandium local run <tenant-id>, replacing <tenant-id> with the ID you noted when you installed the CLI.

  2. The CLI will warn that it may refresh the tenant's secrets and ask you to confirm. Enter y.

You should see something like this logged:

This may refresh the secrets on tenant my-tenant (1234) of integration pokemon (5678). Are you sure you want to do this? (y/n)
y
******
[2026-09-08 10:15:02:123] [index] INFO: Hello from a Pandium integration, written in TypeScript!
[2026-09-08 10:15:02:124] [index] INFO: This run is in mode: normal
[2026-09-08 10:15:02:124] [index] INFO: Tenant configs: {"boolean_1":"true"}
[2026-09-08 10:15:02:125] [index] INFO: new random number: 482913
[2026-09-08 10:15:02:125] [lib] INFO: updating metadata with {"random_number":482913}
{"random_number":482913}
******
Pandium run status: ✅ Success

The starter code just ran in normal mode with your tenant's secrets and configs, and you never had to look up your Slack token! Everything between the two rows of asterisks is your integration's own output, and the CLI reports the run's status at the end. The rest of this tutorial only shows the integration's output when describing what to expect from a run.

A few things are worth noticing about the starter code before you change it:

  • src/lib.ts defines a Pandium class. Pandium.fromEnv() gathers up everything Pandium passed to the run: pandium.config holds the tenant's connection settings (the PAN_CFG_ variables), pandium.secrets holds its secrets (PAN_SEC_), and context (PAN_CTX_) is exposed through methods like pandium.runMode().

  • Logs are written with a log4js logger, which prints to stderr. When writing an integration to run on Pandium, the standard out is reserved for one thing: the last line printed there is saved by Pandium as the tenant's metadata. That's what pandium.updateMetadata is doing with the random number, and you will use it to keep track of the Pokémon of the day later on.

  • The run function branches on run mode. A Pandium integration can run in normal, init, or webhook mode, but the Academy only needs a normal sync for now.

None of the starter's demo logic (random numbers, dynamic colors, webhooks) is relevant to the Pokémon Trainer Academy, so let's clear it out.

  1. In src/index.ts remove the run function and simplify main so that it only logs the run mode and the tenant configs. Your src/index.ts should now look like this:

  1. Run pandium local build && pandium local run <tenant-id> again. Now only two lines should be logged:

If you ever need to override a value for a local run, the CLI will read a .env file in your integration folder and let its values take precedence over the ones saved on Pandium. If you do add one, put it in your .gitignore so secrets are never pushed to your remote repository.

The configs logged here are the irrelevant options from the starter files' PANDIUM.yaml that you saw when you created your tenant. Let's update the PANDIUM.yaml to remove them.

Last updated

Was this helpful?