Skip to main content

Using environment variables with the Slack CLI

Storing and using environment variables in an application allows for certain variables to be maintained outside of the code of the application. You can use environment variables from within Slack functions, triggers, and manifests.

Using environment variables with a custom function

When accessing environment variables from within a custom function, where you store them differs when the app is local versus deployed.

Storing local environment variables

Local environment variables are stored in a .env file at the root of the project and made available for use in custom functions via the env context property.

A local .env file might look like this:

MY_ENV_VAR=asdf1234

Note that changes to your .env file will be reflected when you restart your local development server.

While the .env file should never be committed to source control for security reasons, you can see a sample .env file we've included in the Timesheet approval sample app and the Incident management sample app.

Storing deployed environment variables

When your app is deployed, it will no longer use the .env file. Instead, you will have to add the environment variables using the env add command. Environment variables added with env add will be made available to your deployed app's custom functions just as they are locally; see examples in the next section.

For the above example, we could run the following command before deploying our app:

slack env add MY_ENV_VAR asdf1234

If your token contains non-alphanumeric characters, wrap it in quotes like this:

slack env add SLACK_API_URL "https://dev<yournumber>.slack.com/api/"

Your environment variables are always encrypted before being stored on our servers and will be automatically decrypted when you use them—including when listing environment variables with slack env list.

Access variables from within function

We can retrieve the MY_ENV_VAR environment variable from within a custom Slack function via the env context property like this:

// functions/my_function.ts

import { DefineFunction, SlackFunction } from "deno-slack-sdk/mod.ts";
import { MyFunctionDefinition } from "functions/myfunction.ts"


export default SlackFunction(MyFunctionDefinition, ({ env }) => {
const myEnvVar = env["MY_ENV_VAR"];
// ...
return { outputs: {} };
});

Environment variables also play an important part in making calls to a third-party API. Learn more about how to do that in the FAQ.

Using environment variables with a trigger or manifest

Accessing environment variables from within a trigger definition or when constructing the manifest differs slightly from custom functions.

Whether your app is being run locally or already deployed, constructing these definitions happens entirely on your machine and so the environment variables stored on your machine are used.

Storing environment variables

Environment variables used in trigger or manifest definitions should be saved in the local .env file for your project as shown above. The values from this file are collected and used when generating these definitions.

Regardless of whether you're working with a local or deployed app, the same values from this file will be used. Read on to learn how to access these stored variables in code.

Accessing variables from a trigger or manifest

The Deno runtime provides a helpful load function to autoload environment variables as part of the dotenv module of the standard library. We'll leverage this to easily access our environment variables.

Including this module in code will automatically import local environment variables for immediate use! Start by adding the latest version of this module to your import_map.json:

test
{
"imports": {
"deno-slack-sdk/": "https://deno.land/x/deno_slack_sdk@a.b.c/",
"deno-slack-api/": "https://deno.land/x/deno_slack_api@x.y.z/",
"std/": "https://deno.land/std@0.202.0/"
}
}

Then, you can import the module into any file that makes use of environment variables and start accessing the environment with Deno.env.get("VARIABLE_NAME") like so:

// manifest.ts
import { Manifest } from "deno-slack-sdk/mod.ts";
import ExampleWorkflow from "./workflows/example_workflow.ts";

import "std/dotenv/load.ts";

export default Manifest({
name: "Chatbot4000",
displayName: Deno.env.get("CHATBOT_DISPLAY_NAME"),
description: "Workflows for communicating with an imagined chatbot",
icon: "assets/icon.png",
workflows: [ExampleWorkflow],
outgoingDomains: [
Deno.env.get("CHATBOT_API_URL")!,
],
botScopes: ["commands", "chat:write", "chat:write.public"],
});

After including this new module, you may have to run deno cache manifest.ts to refresh your local dependency cache.

Variable values such as these are commonly used to specify outgoing domains used by functions, channel IDs for event triggers, or client IDs of an external authentication provider. But, don't let that limit you — environment variables can be used in so many other places!

Requiring environment variables values

Setting values for environment variables can sometimes be forgotten, which can cause problems at runtime. Catching errors for these missing values early is often better than waiting for that runtime problem.

Including a ! with your call to Deno.env.get() will ensure this value is defined at the time of building a definition and will throw an error otherwise.

The previous example uses this pattern to ensure an outgoing domain is always set:

  outgoingDomains: [
Deno.env.get("CHATBOT_API_URL")!,
],

With this addition, running slack deploy without defining a value for CHATBOT_API_URL in the .env file will throw an error to give you a chance to set it before actually deploying!

Enabling debug mode

The included environment variable SLACK_DEBUG can enable a basic debug mode. Set SLACK_DEBUG to true to have all function-related payloads logged.

For local apps, add the following to your .env file:

SLACK_DEBUG=true

For deployed apps, run the following command before deployment:

slack env add SLACK_DEBUG true

Included local and deployed variables

Slack provides two environment variables by default, SLACK_WORKSPACE and SLACK_ENV. The workspace name is specified by SLACK_WORKSPACE and SLACK_ENV provides a distinction between the local and deployed app. Use these values if you want to have different values based on the workspace or environment that the app is installed in.

These variables are automatically included when generating the manifest or triggers only. For access from within a custom function, these variables can be set from the .env file or with the env add command.

A custom WorkspaceMapSchema can be created and used with these variables to decide which values to use for certain instances of an app. This can be used as an alternative to a local .env file or in conjunction with it. The following snippet works well for inclusion in your app manifest, or for triggers (for example, to change event trigger channel IDs):

// Custom schemas can be defined for workspace values
type WorkspaceSchema = { channel_id: string };
type WorkspaceMapSchema = {
[workspace: string]: {
[environment: string]: WorkspaceSchema;
};
};

// Custom values can be set for each known workspace
export const workspaceValues: WorkspaceMapSchema = {
beagoodhost: {
deployed: {
channel_id: "C123ABC456",
},
local: {
channel_id: "C123ABC456",
},
},
sandbox: {
deployed: {
channel_id: "C222BBB222",
},
local: {
channel_id: "C222BBB222",
},
},
};

// Fallback options can also be defined
export const defaultValues: WorkspaceSchema = {
channel_id: "{{data.channel_id}}",
};

// Included environment variables will determine which value is used
const environment = Deno.env.get("SLACK_ENV") || "";
const workspace = Deno.env.get("SLACK_WORKSPACE") || "";
const { channel_id } = workspaceValues[workspace]?.[environment] ??
defaultValues;