agentsclimarketplace

Clickup multi env setup

Skill ComeOnOliver/skillshub/skills/jeremylongshore/claude-code-plugins-plus-skills/clickup-multi-env-setup

🧠 The right skill, one API call. AI agent skills registry with token-efficient skill resolution. 5,000+ skills from 500+ top repos.

Install
npx -y skills add ComeOnOliver/skillshub --skill clickup-multi-env-setup

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

What its author says it does

Copied from the file, not written here

Configure ClickUp API access across dev, staging, and production environments with per-environment tokens and workspace isolation. Trigger: "clickup environments", "clickup staging", "clickup dev prod", "clickup environment setup", "clickup config by env", "clickup multi-env".

The file declares its own license as MIT. That is the author’s claim about this one file, and it is not the same thing as the license GitHub reports for the repository, which is listed with the other numbers below.

SKILL.md

5.8 KB, ~1.3k tokens by cl100k_base, as published. Nobody here has run it

ClickUp Multi-Environment Setup

Overview

Configure separate ClickUp workspaces and API tokens for development, staging, and production. ClickUp does not have sandbox environments, so the recommended approach is separate workspaces with separate tokens per environment.

Environment Strategy

EnvironmentWorkspaceTokenRate LimitPurpose
DevelopmentDev workspacePersonal token100 req/minLocal development, testing
StagingStaging workspaceService token100 req/minIntegration testing, QA
ProductionProduction workspaceService tokenPer planLive traffic

Key point: All ClickUp API calls go to https://api.clickup.com/api/v2/ regardless of environment. Environment isolation comes from using different tokens that are authorized for different workspaces.

Configuration

// src/config/clickup.ts
interface ClickUpEnvConfig {
  token: string;
  teamId: string;
  defaultListId?: string;
  timeout: number;
  retries: number;
  cacheEnabled: boolean;
  cacheTtlMs: number;
}

function getClickUpConfig(): ClickUpEnvConfig {
  const env = process.env.NODE_ENV ?? 'development';

  const base = {
    timeout: 30000,
    retries: 3,
    cacheEnabled: true,
    cacheTtlMs: 60000,
  };

  switch (env) {
    case 'production':
      return {
        ...base,
        token: requireEnv('CLICKUP_API_TOKEN_PROD'),
        teamId: requireEnv('CLICKUP_TEAM_ID_PROD'),
        retries: 5,          // More retries in prod
        cacheTtlMs: 300000,  // 5 min cache in prod
      };
    case 'staging':
      return {
        ...base,
        token: requireEnv('CLICKUP_API_TOKEN_STAGING'),
        teamId: requireEnv('CLICKUP_TEAM_ID_STAGING'),
      };
    default:
      return {
        ...base,
        token: requireEnv('CLICKUP_API_TOKEN'),
        teamId: process.env.CLICKUP_TEAM_ID ?? '',
        cacheEnabled: false,  // No cache in dev for fresh data
      };
  }
}

function requireEnv(key: string): string {
  const value = process.env[key];
  if (!value) throw new Error(`Missing required env var: ${key}`);
  return value;
}

Environment Files

# .env.development (local dev, git-ignored)
CLICKUP_API_TOKEN=pk_dev_12345_ABCDEF
CLICKUP_TEAM_ID=1111111

# .env.staging (CI/CD only, git-ignored)
CLICKUP_API_TOKEN_STAGING=pk_stg_67890_GHIJKL
CLICKUP_TEAM_ID_STAGING=2222222

# .env.production (secrets manager only, NEVER in files)
# CLICKUP_API_TOKEN_PROD=pk_prod_... (stored in Vault/AWS/GCP)
# CLICKUP_TEAM_ID_PROD=3333333
# .env.example (commit this as template)
CLICKUP_API_TOKEN=pk_your_token_here
CLICKUP_TEAM_ID=your_team_id_here

Secrets by Platform

# GitHub Actions
gh secret set CLICKUP_API_TOKEN_STAGING --body "pk_stg_..."
gh secret set CLICKUP_API_TOKEN_PROD --body "pk_prod_..."

# AWS Secrets Manager
aws secretsmanager create-secret \
  --name clickup/production/api-token \
  --secret-string "pk_prod_..."

# GCP Secret Manager
echo -n "pk_prod_..." | gcloud secrets create clickup-api-token-prod --data-file=-

# HashiCorp Vault
vault kv put secret/clickup/production api_token="pk_prod_..."

Environment Guards

// Prevent destructive operations in production
function guardDestructiveOp(operation: string): void {
  const config = getClickUpConfig();
  const env = process.env.NODE_ENV ?? 'development';

  // In production, require explicit confirmation
  if (env === 'production' && !process.env.CLICKUP_ALLOW_DESTRUCTIVE) {
    throw new Error(
      `${operation} blocked in production. Set CLICKUP_ALLOW_DESTRUCTIVE=true to override.`
    );
  }
}

// Usage: prevent bulk delete in prod
async function deleteCompletedTasks(listId: string) {
  guardDestructiveOp('deleteCompletedTasks');

  const { tasks } = await clickupRequest(
    `/list/${listId}/task?statuses[]=complete`
  );
  for (const task of tasks) {
    await clickupRequest(`/task/${task.id}`, { method: 'DELETE' });
  }
}

Verify Environment Setup

#!/bin/bash
# verify-clickup-env.sh
echo "=== ClickUp Environment Verification ==="
echo "NODE_ENV: ${NODE_ENV:-development}"

for ENV_SUFFIX in "" "_STAGING" "_PROD"; do
  TOKEN_VAR="CLICKUP_API_TOKEN${ENV_SUFFIX}"
  TOKEN="${!TOKEN_VAR}"

  if [ -z "$TOKEN" ]; then
    echo "${TOKEN_VAR}: NOT SET"
    continue
  fi

  echo -n "${TOKEN_VAR}: "
  RESULT=$(curl -sf https://api.clickup.com/api/v2/user \
    -H "Authorization: $TOKEN" 2>/dev/null)
  if [ $? -eq 0 ]; then
    USERNAME=$(echo "$RESULT" | python3 -c "import sys,json; print(json.load(sys.stdin)['user']['username'])" 2>/dev/null)
    echo "OK (user: $USERNAME)"
  else
    echo "FAILED"
  fi
done

Error Handling

IssueCauseSolution
Wrong workspace in prodUsing dev tokenVerify CLICKUP_TEAM_ID matches token's workspace
Missing env varNot configuredCheck .env file or secrets manager
Cross-env data leakShared tokenUse separate tokens per environment
Destructive op in prodMissing guardImplement environment guards

Resources

Next Steps

For observability setup, see clickup-observability.

Keep looking

Skills are one crate of 328,083. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.