Skip to content

Comments

feat: env command in the cli #2485

Merged
myftija merged 5 commits intomainfrom
env-vars-command
Sep 9, 2025
Merged

feat: env command in the cli #2485
myftija merged 5 commits intomainfrom
env-vars-command

Conversation

@myftija
Copy link
Collaborator

@myftija myftija commented Sep 9, 2025

This PR adds a couple of env commands to list and view environment variables
of a project. The env pull command also enables exporting the env vars into a file.

We might extend this to also support creating and deleting env vars in the future.

@changeset-bot
Copy link

changeset-bot bot commented Sep 9, 2025

🦋 Changeset detected

Latest commit: 5e12595

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 23 packages
Name Type
trigger.dev Patch
d3-chat Patch
references-d3-openai-agents Patch
references-nextjs-realtime Patch
@trigger.dev/build Patch
@trigger.dev/core Patch
@trigger.dev/python Patch
@trigger.dev/react-hooks Patch
@trigger.dev/redis-worker Patch
@trigger.dev/rsc Patch
@trigger.dev/schema-to-json Patch
@trigger.dev/sdk Patch
@trigger.dev/database Patch
@trigger.dev/otlp-importer Patch
@internal/cache Patch
@internal/clickhouse Patch
@internal/redis Patch
@internal/replication Patch
@internal/run-engine Patch
@internal/schedule-engine Patch
@internal/testcontainers Patch
@internal/tracing Patch
@internal/zod-worker Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Sep 9, 2025

Walkthrough

Adds a changeset that bumps the "trigger.dev" package to a patch version and registers a new top-level CLI command env. Introduces packages/cli-v3/src/commands/env.ts which implements env subcommands list, get, and pull with zod-based option schemas, telemetry wrapping, initial banner printing, and project/environment resolution (including embedded login and client creation). The new commands support tabular and raw outputs, suggestion hints for missing variables, and writing non-TRIGGER_ variables to a local dotenv file with overwrite prompting and a --force option. The CLI entry is wired to call configureEnvCommand(program).

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Pre-merge checks (1 passed, 2 warnings)

❌ Failed checks (2 warnings)
Check name Status Explanation Resolution
Description Check ⚠️ Warning The current description does not adhere to the repository’s required template, as it is missing the issue closure line, the checklist section, detailed testing steps, changelog entry, and screenshots section. Please update the description to include “Closes #”, the completed checklist, a Testing section with steps taken, a Changelog summary, and a Screenshots section as outlined in the repository template.
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (1 passed)
Check name Status Explanation
Title Check ✅ Passed The title succinctly and accurately summarizes the primary change by highlighting the introduction of the new env CLI command, and it follows the conventional commit style required for feature additions.

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 31f0870 and 5e12595.

📒 Files selected for processing (1)
  • .changeset/serious-doors-call.md (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • .changeset/serious-doors-call.md
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (16)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (3, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (5, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (4, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (6, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (8, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (7, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (2, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (2, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (6, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (4, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (1, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (1, 8)
  • GitHub Check: units / packages / 🧪 Unit Tests: Packages (1, 1)
  • GitHub Check: e2e / 🧪 CLI v3 tests (windows-latest - npm)
  • GitHub Check: e2e / 🧪 CLI v3 tests (windows-latest - pnpm)
  • GitHub Check: typecheck / typecheck

Pre-merge checks (1 passed, 2 warnings)

❌ Failed checks (2 warnings)
Check name Status Explanation Resolution
Description Check ⚠️ Warning The current description omits the required template sections—such as the issue reference (“Closes #…”), checklist, testing steps, changelog entry, and screenshots—leaving it incomplete relative to the repository’s PR description standard. Please update the PR description to follow the repository template by adding “Closes #”, completing the checklist, detailing testing steps, providing a changelog summary, and including any relevant screenshots.
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (1 passed)
Check name Status Explanation
Title Check ✅ Passed The title succinctly and accurately describes the core enhancement by highlighting the addition of an “env” command to the CLI, which directly reflects the main purpose and changes of the pull request. It is concise, specific, and free of extraneous detail, ensuring clarity for anyone reviewing the project history. This aligns well with the added commands and related functionality introduced in the diff.
✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch env-vars-command

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@myftija myftija changed the title feat: list and view env vars in the cli feat: env cli command Sep 9, 2025
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (9)
.changeset/serious-doors-call.md (1)

5-5: Clarify the scope of the new CLI subcommands in the changeset summary

Mention list, get, and pull (and that pull can write to a file) for clearer release notes.

Apply this diff:

-Added new CLI command to list and view environment variables
+Added env CLI with subcommands: list, get, and pull (export to .env) for managing project environment variables
packages/cli-v3/src/commands/env.ts (8)

63-66: Help text omits the supported ‘production’ alias

Schemas accept “production”, but the help strings list only prod/staging/preview. Add “production” to avoid confusion.

-        "The environment to list variables from (prod, staging, preview)",
+        "The environment to list variables from (prod, production, staging, preview)",
-        "The environment to get the variable from (prod, staging, preview)",
+        "The environment to get the variable from (prod, production, staging, preview)",
-        "The environment to pull variables from (prod, staging, preview)",
+        "The environment to pull variables from (prod, production, staging, preview)",

Also applies to: 89-92, 114-117


22-28: Validate: require either --config or --project-ref

As written, a missing project reference/config bubbles up as “Failed to get project client”. Validate early for clear UX.

-const EnvListOptions = CommonCommandOptions.extend({
+const EnvListOptions = CommonCommandOptions.extend({
   config: z.string().optional(),
   projectRef: z.string().optional(),
   showValues: z.boolean().default(false),
   env: z.enum(["prod", "staging", "preview", "production"]).default("prod"),
   branch: z.string().optional(),
-});
+}).superRefine((d, ctx) => {
+  if (!d.config && !d.projectRef) {
+    ctx.addIssue({
+      code: z.ZodIssueCode.custom,
+      message: "Either --config or --project-ref is required.",
+      path: ["projectRef"],
+    });
+  }
+});

30-37: Apply the same validation to ‘get’ options

-const EnvGetOptions = CommonCommandOptions.extend({
+const EnvGetOptions = CommonCommandOptions.extend({
   config: z.string().optional(),
   projectRef: z.string().optional(),
   name: z.string(),
   raw: z.boolean().default(false),
   env: z.enum(["prod", "staging", "preview", "production"]).default("prod"),
   branch: z.string().optional(),
-});
+}).superRefine((d, ctx) => {
+  if (!d.config && !d.projectRef) {
+    ctx.addIssue({
+      code: z.ZodIssueCode.custom,
+      message: "Either --config or --project-ref is required.",
+      path: ["projectRef"],
+    });
+  }
+});

39-46: Apply the same validation to ‘pull’ options

-const EnvPullOptions = CommonCommandOptions.extend({
+const EnvPullOptions = CommonCommandOptions.extend({
   config: z.string().optional(),
   projectRef: z.string().optional(),
   output: z.string().default(".env.local"),
   force: z.boolean().default(false),
   env: z.enum(["prod", "staging", "preview", "production"]).default("prod"),
   branch: z.string().optional(),
-});
+}).superRefine((d, ctx) => {
+  if (!d.config && !d.projectRef) {
+    ctx.addIssue({
+      code: z.ZodIssueCode.custom,
+      message: "Either --config or --project-ref is required.",
+      path: ["projectRef"],
+    });
+  }
+});

176-185: Connection error message may show ‘undefined’ URL

On login “fetch failed”, authorization.auth?.apiUrl is typically undefined. Use the requested apiUrl instead.

-    if (authorization.error === "fetch failed") {
-      throw new Error(
-        `Failed to connect to ${authorization.auth?.apiUrl}. Are you sure it's the correct URL?`
-      );
-    }
+    if (authorization.error === "fetch failed") {
+      throw new Error(
+        `Failed to connect to ${options.apiUrl}. Are you sure it's the correct URL?`
+      );
+    }

340-343: Avoid hard process.exit(1); throw to let wrappers handle telemetry/exit code

Direct exit bypasses wrapCommandAction/handleTelemetry and can skip consistent logging. Throw instead.

-    const envInfo = branch ? `${env} (${branch})` : env;
-    outro(`Project: ${projectRef} | Environment: ${envInfo}`);
-    process.exit(1);
+    const envInfo = branch ? `${env} (${branch})` : env;
+    outro(`Project: ${projectRef} | Environment: ${envInfo}`);
+    throw new Error(`Environment variable "${options.name}" not found`);

241-246: DRY: factor TRIGGER_ filtering into a small helper

Same filter is duplicated in list and pull. Extract to a function for consistency and testability.

Also applies to: 373-378


16-16: Remove unused import ‘upsertBranch’

It isn’t used in this module.

-import { getProjectClient, upsertBranch } from "../utilities/session.js";
+import { getProjectClient } from "../utilities/session.js";
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 71060d9 and 87014d5.

📒 Files selected for processing (3)
  • .changeset/serious-doors-call.md (1 hunks)
  • packages/cli-v3/src/cli/index.ts (2 hunks)
  • packages/cli-v3/src/commands/env.ts (1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

**/*.{ts,tsx}: Always prefer using isomorphic code like fetch, ReadableStream, etc. instead of Node.js specific code
For TypeScript, we usually use types over interfaces
Avoid enums
No default exports, use function declarations

Files:

  • packages/cli-v3/src/commands/env.ts
  • packages/cli-v3/src/cli/index.ts
🧠 Learnings (1)
📚 Learning: 2025-08-29T10:06:49.293Z
Learnt from: CR
PR: triggerdotdev/trigger.dev#0
File: .cursor/rules/webapp.mdc:0-0
Timestamp: 2025-08-29T10:06:49.293Z
Learning: Applies to {apps/webapp/app/**/*.server.{ts,tsx},apps/webapp/app/routes/**/*.ts} : Access environment variables only via the env export from app/env.server.ts; do not reference process.env directly

Applied to files:

  • packages/cli-v3/src/commands/env.ts
🧬 Code graph analysis (2)
packages/cli-v3/src/commands/env.ts (5)
packages/cli-v3/src/cli/common.ts (3)
  • commonOptions (21-31)
  • handleTelemetry (37-43)
  • wrapCommandAction (45-82)
packages/cli-v3/src/commands/login.ts (1)
  • login (76-359)
packages/cli-v3/src/config.ts (1)
  • loadConfig (33-47)
packages/cli-v3/src/utilities/session.ts (1)
  • getProjectClient (84-118)
packages/cli-v3/src/utilities/windows.ts (1)
  • spinner (85-85)
packages/cli-v3/src/cli/index.ts (1)
packages/cli-v3/src/commands/env.ts (1)
  • configureEnvCommand (48-129)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (22)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (7, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (6, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (4, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (5, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (3, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (8, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (3, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (1, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (2, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (5, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (6, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (7, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (4, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (2, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (1, 8)
  • GitHub Check: units / packages / 🧪 Unit Tests: Packages (1, 1)
  • GitHub Check: e2e / 🧪 CLI v3 tests (windows-latest - pnpm)
  • GitHub Check: e2e / 🧪 CLI v3 tests (ubuntu-latest - pnpm)
  • GitHub Check: e2e / 🧪 CLI v3 tests (ubuntu-latest - npm)
  • GitHub Check: e2e / 🧪 CLI v3 tests (windows-latest - npm)
  • GitHub Check: typecheck / typecheck
  • GitHub Check: Analyze (javascript-typescript)
🔇 Additional comments (1)
packages/cli-v3/src/cli/index.ts (1)

5-5: Wiring looks good

Import and registration order are consistent with the rest of the CLI. No issues.

Also applies to: 32-32

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

♻️ Duplicate comments (1)
packages/cli-v3/src/commands/env.ts (1)

388-389: Nice: secure file perms on create and write.

Good adoption of restrictive perms and safe file creation.

Also applies to: 410-413

🧹 Nitpick comments (5)
packages/cli-v3/src/commands/env.ts (5)

15-15: Remove unused import (upsertBranch).

This avoids noise and keeps the bundle lean.

Apply this diff:

-import { getProjectClient, upsertBranch } from "../utilities/session.js";
+import { getProjectClient } from "../utilities/session.js";

63-66: Help text should mention the accepted production alias.

Schemas accept "production" but CLI help omits it; align to reduce confusion.

Apply this diff:

-        "The environment to list variables from (prod, staging, preview)",
+        "The environment to list variables from (prod|production, staging, preview)",
@@
-        "The environment to get the variable from (prod, staging, preview)",
+        "The environment to get the variable from (prod|production, staging, preview)",
@@
-        "The environment to pull variables from (prod, staging, preview)",
+        "The environment to pull variables from (prod|production, staging, preview)",

Also applies to: 89-92, 114-117


320-343: Honor --raw silence and avoid process.exit(1); set exitCode and return.

This keeps scripting-friendly behavior (no extra output) and avoids hard exits inside subcommands.

Apply this diff:

-  if (value === undefined) {
-    if (options.raw) {
-      throw new Error(`Environment variable "${options.name}" not found`);
-    }
+  if (value === undefined) {
+    if (options.raw) {
+      // Silent non-zero for scripting
+      process.exitCode = 1;
+      return;
+    }
@@
-    const envInfo = branch ? `${env} (${branch})` : env;
-    outro(`Project: ${projectRef} | Environment: ${envInfo}`);
-    process.exit(1);
+    const envInfo = branch ? `${env} (${branch})` : env;
+    outro(`Project: ${projectRef} | Environment: ${envInfo}`);
+    process.exitCode = 1;
+    return;
   }
 
-  if (options.raw) {
+  if (options.raw) {
     console.log(value || "");
     return;
   }

Also applies to: 345-348


394-404: Non-interactive/CI safety: fail fast if file exists and --force not set.

Avoids hanging on a prompt in CI.

Apply this diff:

   if (error && "code" in error && error.code === "EEXIST" && !options.force) {
+    if (process.env.CI) {
+      throw new Error(
+        `File ${options.output} already exists (CI detected). Use --force or choose a different --output.`
+      );
+    }
     const shouldOverwrite = await confirm({
       message: `File ${options.output} already exists. Overwrite?`,
       initialValue: false,
     });

69-71: Optional confirmation before printing secrets with --show-values.

A quick confirmation helps prevent accidental secret exposure in shared terminals.

Apply this diff:

-      .option(
-        "--show-values",
-        "Show the actual values of environment variables, including secret values"
-      )
+      .option(
+        "--show-values",
+        "Show the actual values of environment variables, including secret values (will prompt to confirm)"
+      )
@@
-  for (const [key, value] of userVariables) {
+  if (options.showValues && !process.env.CI) {
+    const proceed = await confirm({
+      message: "This will print sensitive values to your terminal. Continue?",
+      initialValue: false,
+    });
+    if (isCancel(proceed) || !proceed) {
+      outro("Cancelled");
+      return;
+    }
+  }
+  for (const [key, value] of userVariables) {
     table.push([key, options.showValues ? value : "******"]);
   }

Also applies to: 277-279

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 87014d5 and 31f0870.

📒 Files selected for processing (1)
  • packages/cli-v3/src/commands/env.ts (1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

**/*.{ts,tsx}: Always prefer using isomorphic code like fetch, ReadableStream, etc. instead of Node.js specific code
For TypeScript, we usually use types over interfaces
Avoid enums
No default exports, use function declarations

Files:

  • packages/cli-v3/src/commands/env.ts
🧠 Learnings (2)
📓 Common learnings
Learnt from: CR
PR: triggerdotdev/trigger.dev#0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-08-18T10:07:17.368Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : Import Trigger.dev APIs from "trigger.dev/sdk/v3" when writing tasks or related utilities
📚 Learning: 2025-08-29T10:06:49.293Z
Learnt from: CR
PR: triggerdotdev/trigger.dev#0
File: .cursor/rules/webapp.mdc:0-0
Timestamp: 2025-08-29T10:06:49.293Z
Learning: Applies to {apps/webapp/app/**/*.server.{ts,tsx},apps/webapp/app/routes/**/*.ts} : Access environment variables only via the env export from app/env.server.ts; do not reference process.env directly

Applied to files:

  • packages/cli-v3/src/commands/env.ts
🧬 Code graph analysis (1)
packages/cli-v3/src/commands/env.ts (6)
packages/cli-v3/src/cli/common.ts (3)
  • commonOptions (21-31)
  • handleTelemetry (37-43)
  • wrapCommandAction (45-82)
packages/cli-v3/src/utilities/initialBanner.ts (1)
  • printInitialBanner (27-63)
packages/cli-v3/src/commands/login.ts (1)
  • login (76-359)
packages/cli-v3/src/config.ts (1)
  • loadConfig (33-47)
packages/cli-v3/src/utilities/session.ts (1)
  • getProjectClient (84-118)
packages/cli-v3/src/utilities/windows.ts (1)
  • spinner (85-85)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (23)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (3, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (5, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (6, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (7, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (1, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (5, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (8, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (8, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (2, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (4, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (3, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (6, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (7, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (2, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (1, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (4, 8)
  • GitHub Check: e2e / 🧪 CLI v3 tests (windows-latest - pnpm)
  • GitHub Check: units / packages / 🧪 Unit Tests: Packages (1, 1)
  • GitHub Check: e2e / 🧪 CLI v3 tests (ubuntu-latest - pnpm)
  • GitHub Check: e2e / 🧪 CLI v3 tests (windows-latest - npm)
  • GitHub Check: e2e / 🧪 CLI v3 tests (ubuntu-latest - npm)
  • GitHub Check: typecheck / typecheck
  • GitHub Check: Analyze (javascript-typescript)
🔇 Additional comments (1)
packages/cli-v3/src/commands/env.ts (1)

434-441: Robust dotenv serialization.

Quoting on whitespace/specials prevents malformed .env lines. LGTM.

@myftija myftija changed the title feat: env cli command feat: env command in the cli Sep 9, 2025
@myftija myftija merged commit 12bef0a into main Sep 9, 2025
31 checks passed
@myftija myftija deleted the env-vars-command branch September 9, 2025 11:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants