Repository: elizaOS/eliza
Pull request #4610: Eliza290/cli command env
Author: login: yungalgo
Labels: name: 1.x
description: V2
Created: 2025-05-16T09:31:45Z | Merged: 2025-05-16T13:49:33Z

**elizaos env list:**

Added warning when no local .env file exists, with guidance to create one from .env.example if available
Added --system flag to show only system information, consistent with existing --global and --local flags

**elizaos env reset:**
Transformed from a simple deletion command to an interactive selection interface
Implemented proper reset functionality that preserves keys but clears values
Added support for both global and local environment files
Added database handling with special consideration for PostgreSQL vs PGLite

**Path handling improvements:**
Fixed env set-path to properly handle tilde (~) expansion for home directories
Added better error handling and messages for invalid paths

**elizaos env interactive:**
Made "Set custom environment path" option in interactive mode work properly
Ensured consistent UI styling and user experience across commands

+ Updated documentation

<!-- This is an auto-generated comment: release notes by coderabbit.ai -->

## Summary by CodeRabbit

- **New Features**
  - Improved environment variable management in the CLI, including enhanced listing, resetting, and setting of environment variables.
  - Added interactive reset functionality, allowing users to select which items to reset with clear descriptions and warnings.
  - The `list` command now offers a `--system` option to display system information.

- **Bug Fixes**
  - Enhanced error handling and user feedback when managing environment variables and related files.

- **Documentation**
  - Updated CLI documentation to clarify new options, interactive reset behavior, and provide improved usage examples.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->


Diff:
diff --git a/packages/cli/src/commands/env.ts b/packages/cli/src/commands/env.ts
index e44d638ed826d..f0ad692dafeab 100644
--- a/packages/cli/src/commands/env.ts
+++ b/packages/cli/src/commands/env.ts
@@ -207,14 +207,33 @@ async function listEnvVars(): Promise<void> {
     }
   }
 
-  if (localEnvPath) {
-    console.info(colors.bold('\nLocal Environment Variables:'));
-    console.info(`Path: ${localEnvPath}`);
-
-    if (!existsSync(localEnvPath)) {
+  // Always display local environment section regardless of whether a file exists
+  console.info(colors.bold('\nLocal Environment Variables:'));
+  const localEnvFilePath = path.join(process.cwd(), '.env');
+  console.info(`Path: ${localEnvFilePath}`);
+
+  if (!existsSync(localEnvFilePath)) {
+    // No local .env file exists, provide guidance to the user
+    console.info(colors.yellow('  No local .env file found'));
+
+    // Check if .env.example exists and suggest copying it as a starting point
+    const exampleEnvPath = path.join(process.cwd(), '.env.example');
+    if (existsSync(exampleEnvPath)) {
+      console.info(colors.red('  ✖ Missing .env file. Create one with:'));
+      console.info(`     ${colors.bold(colors.green('cp .env.example .env'))}`);
+    } else {
+      console.info(
+        colors.red(
+          '  ✖ Missing .env file. Create one in your project directory to set local environment variables.'
+        )
+      );
+    }
+  } else {
+    // .env file exists, parse and display its contents
+    const localEnvVars = await parseEnvFile(localEnvFilePath);
+    if (Object.keys(localEnvVars).length === 0) {
       console.info('  No local environment variables set');
     } else {
-      const localEnvVars = await parseEnvFile(localEnvPath);
       for (const [key, value] of Object.entries(localEnvVars)) {
         console.info(`  ${colors.green(key)}: ${maskedValue(value)}`);
       }
@@ -418,75 +437,289 @@ async function addNewVariable(envPath: string, envVars: Record<string, string>):
 }
 
 /**
- * Reset all environment variables and wipe the cache folder
+ * Helper function to reset an environment file by keeping keys but clearing values
+ * @param filePath Path to the environment file
+ * @returns A boolean indicating success/failure
  */
-async function resetEnv(yes = false): Promise<void> {
-  console.log('resetEnv called with yes =', yes);
-  let confirm = true;
-  if (!yes) {
-    const resp = await prompts({
-      type: 'confirm',
-      name: 'confirm',
-      message:
-        'This will delete all environment variables and wipe the cache folder. Are you sure?',
-      initial: false,
-    });
-    confirm = resp.confirm;
+async function resetEnvFile(filePath: string): Promise<boolean> {
+  try {
+    if (!existsSync(filePath)) {
+      return false;
+    }
+
+    const envVars = await parseEnvFile(filePath);
+    if (Object.keys(envVars).length === 0) {
+      return false; // No variables to reset
+    }
+
+    const resetVars = Object.keys(envVars).reduce(
+      (acc, key) => {
+        acc[key] = '';
+        return acc;
+      },
+      {} as Record<string, string>
+    );
+
+    await writeEnvFile(filePath, resetVars);
+    return true;
+  } catch (error) {
+    console.error(`Error resetting environment file at ${filePath}: ${error.message}`);
+    return false;
   }
-  if (!confirm) {
-    console.log('Reset cancelled.');
-    return;
+}
+
+// Reset operation types and helper functions
+type ResetTarget = 'globalEnv' | 'localEnv' | 'cache' | 'globalDb' | 'localDb';
+type ResetAction = 'reset' | 'deleted' | 'skipped' | 'warning';
+
+interface ResetItem {
+  title: string;
+  value: ResetTarget;
+  description?: string;
+  selected?: boolean;
+}
+
+/**
+ * Delete a directory with error handling
+ * @param dir Directory path to delete
+ * @param actions Action log collection to update
+ * @param label Description label for this operation
+ * @returns Success or failure
+ */
+async function safeDeleteDirectory(
+  dir: string,
+  actions: Record<string, string[]>,
+  label: string
+): Promise<boolean> {
+  if (!existsSync(dir)) {
+    actions.skipped.push(`${label} (not found)`);
+    return false;
   }
 
-  // Get paths
+  try {
+    await rimraf(dir);
+    if (!existsSync(dir)) {
+      actions.deleted.push(label);
+      return true;
+    } else {
+      actions.warnings.push(`Failed to delete ${label.toLowerCase()}`);
+      return false;
+    }
+  } catch (error) {
+    actions.warnings.push(`Failed to delete ${label.toLowerCase()}: ${error.message}`);
+    return false;
+  }
+}
+
+/**
+ * Reset environment variables and selected folders
+ */
+async function resetEnv(yes = false): Promise<void> {
+  // Get all relevant paths
   const homeDir = os.homedir();
   const elizaDir = path.join(homeDir, '.eliza');
   const globalEnvPath = await getGlobalEnvPath();
   const cacheDir = path.join(elizaDir, 'cache');
-  const dbDir = path.join(elizaDir, 'projects', stringToUuid(process.cwd()), 'db');
+  const projectUuid = stringToUuid(process.cwd());
+  const globalDbDir = path.join(elizaDir, 'projects', projectUuid, 'db');
+  const globalPgliteDir = path.join(elizaDir, 'projects', projectUuid, 'pglite');
+  const localEnvPath = path.join(process.cwd(), '.env');
+  const localDbDir = path.join(process.cwd(), 'elizadb');
 
-  // Remove global .env file
-  if (existsSync(globalEnvPath)) {
-    await fs.unlink(globalEnvPath);
-    console.log('Removed global .env file');
+  // Check if external Postgres is in use
+  let usingExternalPostgres = false;
+  try {
+    const globalEnvVars = await parseEnvFile(globalEnvPath);
+    const localEnvVars = await parseEnvFile(localEnvPath);
+    usingExternalPostgres =
+      (globalEnvVars.POSTGRES_URL && globalEnvVars.POSTGRES_URL.trim() !== '') ||
+      (localEnvVars.POSTGRES_URL && localEnvVars.POSTGRES_URL.trim() !== '');
+  } catch (error) {
+    // Ignore errors
   }
 
-  // Clear custom env path if set
-  if (existsSync(CONFIG_FILE)) {
-    try {
-      const content = await fs.readFile(CONFIG_FILE, 'utf-8');
-      const config = JSON.parse(content);
+  // Create reset item options
+  const resetItems: ResetItem[] = [
+    {
+      title: 'Global environment variables',
+      value: 'globalEnv',
+      description: 'Reset values in global .env file',
+      selected: false,
+    },
+    {
+      title: 'Local environment variables',
+      value: 'localEnv',
+      description: 'Reset values in local .env file',
+      selected: false,
+    },
+    {
+      title: 'Cache folder',
+      value: 'cache',
+      description: existsSync(cacheDir)
+        ? 'Delete the cache folder'
+        : 'Cache folder not found, nothing to delete',
+      selected: false,
+    },
+    {
+      title: 'Global database files',
+      value: 'globalDb',
+      description:
+        !existsSync(globalDbDir) && !existsSync(globalPgliteDir)
+          ? 'Global database files not found, nothing to delete'
+          : usingExternalPostgres
+            ? 'WARNING: External PostgreSQL database detected - only local files will be removed'
+            : 'Delete global database files',
+      selected: false,
+    },
+    {
+      title: 'Local database files',
+      value: 'localDb',
+      description: existsSync(localDbDir)
+        ? 'Delete local database files'
+        : 'Local database folder not found, nothing to delete',
+      selected: false,
+    },
+  ];
+
+  // Get selected items (from options or defaults)
+  let selectedValues: ResetTarget[] = [];
+
+  if (yes) {
+    // When using --yes flag, include all reset items rather than relying on selected flag
+    selectedValues = resetItems.map((item) => item.value);
+  } else {
+    // Prompt user to select items with styling matching interactive mode
+    const { selections } = await prompts({
+      type: 'multiselect',
+      name: 'selections',
+      message: colors.cyan(colors.bold('Select items to reset:')),
+      choices: resetItems,
+      instructions: false,
+      hint: '- Space to select, Enter to confirm',
+      min: 1,
+    });
 
-      if (config.envPath) {
-        const { envPath, ...restConfig } = config;
-        await fs.writeFile(CONFIG_FILE, JSON.stringify(restConfig, null, 2));
-        console.log('Cleared custom environment path setting');
+    if (!selections || selections.length === 0) {
+      console.log('No items selected. Reset cancelled.');
+      return;
+    }
+
+    selectedValues = selections;
+
+    // Show selected items
+    console.log('\nYou selected:');
+    for (const value of selectedValues) {
+      const item = resetItems.find((item) => item.value === value);
+      console.log(`  • ${item.title}`);
+    }
+
+    // Final confirmation
+    const { confirm } = await prompts({
+      type: 'confirm',
+      name: 'confirm',
+      message: 'Are you sure you want to reset the selected items?',
+      initial: false,
+    });
+
+    if (!confirm) {
+      console.log('Reset cancelled.');
+      return;
+    }
+  }
+
+  // Track reset results
+  const actions: Record<ResetAction, string[]> = {
+    reset: [],
+    deleted: [],
+    skipped: [],
+    warning: [],
+  };
+
+  // Process each selected item
+  for (const target of selectedValues) {
+    switch (target) {
+      case 'globalEnv':
+        if (await resetEnvFile(globalEnvPath)) {
+          actions.reset.push('Global environment variables');
+        } else {
+          actions.skipped.push('Global environment variables (no file or empty)');
+        }
+        break;
+
+      case 'localEnv':
+        if (await resetEnvFile(localEnvPath)) {
+          actions.reset.push('Local environment variables');
+        } else {
+          actions.skipped.push('Local environment variables (no file or empty)');
+        }
+        break;
+
+      case 'cache':
+        await safeDeleteDirectory(cacheDir, actions, 'Cache folder');
+        break;
+
+      case 'globalDb': {
+        if (usingExternalPostgres) {
+          actions.warning.push(
+            'External PostgreSQL database detected. Database data cannot be reset but local database cache files will be removed.'
+          );
+        }
+
+        let anyGlobalDbDeleted = false;
+
+        // Try deleting db dir
+        if (existsSync(globalDbDir)) {
+          if (await safeDeleteDirectory(globalDbDir, actions, 'Global database folder')) {
+            anyGlobalDbDeleted = true;
+          }
+        }
+
+        // Try deleting PGLite dir
+        if (existsSync(globalPgliteDir)) {
+          if (
+            await safeDeleteDirectory(globalPgliteDir, actions, 'Global PGLite database folder')
+          ) {
+            anyGlobalDbDeleted = true;
+          }
+        }
+
+        // If neither existed and nothing was deleted
+        if (!anyGlobalDbDeleted && !existsSync(globalDbDir) && !existsSync(globalPgliteDir)) {
+          actions.skipped.push('Global database files (not found)');
+        }
+        break;
       }
-    } catch (error) {
-      console.error(`Error clearing custom env path: ${error.message}`);
+
+      case 'localDb':
+        await safeDeleteDirectory(localDbDir, actions, 'Local database folder');
+        break;
     }
   }
 
-  // Wipe cache folder
-  if (existsSync(cacheDir)) {
-    await rimraf(cacheDir);
-    console.log('Wiped cache folder');
+  // Print summary report
+  console.log(colors.bold('\nReset Summary:'));
+
+  if (actions.reset.length > 0) {
+    console.log(colors.green('  Values Cleared:'));
+    actions.reset.forEach((item) => console.log(`    • ${item}`));
   }
 
-  // Ask if user wants to reset database too
-  const { resetDb } = await prompts({
-    type: 'confirm',
-    name: 'resetDb',
-    message: 'Do you also want to reset the database folder?',
-    initial: false,
-  });
+  if (actions.deleted.length > 0) {
+    console.log(colors.green('  Deleted:'));
+    actions.deleted.forEach((item) => console.log(`    • ${item}`));
+  }
 
-  if (resetDb && existsSync(dbDir)) {
-    await rimraf(dbDir);
-    console.log('Wiped database folder');
+  if (actions.skipped.length > 0) {
+    console.log(colors.yellow('  Skipped:'));
+    actions.skipped.forEach((item) => console.log(`    • ${item}`));
   }
 
-  console.log('Environment reset complete');
+  if (actions.warning.length > 0) {
+    console.log(colors.red('  Warnings:'));
+    actions.warning.forEach((item) => console.log(`    • ${item}`));
+  }
+
+  console.log(colors.bold('\nEnvironment reset complete'));
 }
 
 /**
@@ -495,6 +728,12 @@ async function resetEnv(yes = false): Promise<void> {
  * @param autoConfirm Automatically confirm prompts
  */
 async function setEnvPath(customPath: string, autoConfirm = false): Promise<void> {
+  // Expand tilde (~) in the path if present
+  if (customPath.startsWith('~')) {
+    // Use string concatenation instead of path.join to preserve slashes
+    customPath = os.homedir() + customPath.substring(1);
+  }
+
   // Validate the path
   const resolvedPath = path.resolve(customPath);
   const isDirectory = existsSync(resolvedPath) && (await fs.stat(resolvedPath)).isDirectory();
@@ -520,8 +759,14 @@ async function setEnvPath(customPath: string, autoConfirm = false): Promise<void
     }
 
     if (createDir) {
-      await fs.mkdir(parentDir, { recursive: true });
-      console.log(`Created directory: ${parentDir}`);
+      try {
+        await fs.mkdir(parentDir, { recursive: true });
+        console.log(`Created directory: ${parentDir}`);
+      } catch (error) {
+        console.error(`Failed to create directory: ${error.message}`);
+        console.info('Custom path not set');
+        return;
+      }
     } else {
       console.info('Custom path not set');
       return;
@@ -563,11 +808,22 @@ export const env = new Command()
 env
   .command('list')
   .description('List all environment variables')
+  .option('--system', 'List only system information')
   .option('--global', 'List only global environment variables')
   .option('--local', 'List only local environment variables')
-  .action(async (options: { global?: boolean; local?: boolean }) => {
+  .action(async (options: { global?: boolean; local?: boolean; system?: boolean }) => {
     try {
-      if (options.local) {
+      if (options.system) {
+        // Show only system information
+        const envInfo = await UserEnvironment.getInstanceInfo();
+        console.info(colors.bold('\nSystem Information:'));
+        console.info(`  Platform: ${colors.cyan(envInfo.os.platform)} (${envInfo.os.release})`);
+        console.info(`  Architecture: ${colors.cyan(envInfo.os.arch)}`);
+        console.info(`  CLI Version: ${colors.cyan(envInfo.cli.version)}`);
+        console.info(
+          `  Package Manager: ${colors.cyan(envInfo.packageManager.name)}${envInfo.packageManager.version ? ` v${envInfo.packageManager.version}` : ''}`
+        );
+      } else if (options.local) {
         const localEnvPath = getLocalEnvPath();
         if (!localEnvPath) {
           console.error('No local .env file found in the current directory');
@@ -635,11 +891,12 @@ env
 // Reset subcommand
 env
   .command('reset')
-  .description('Reset all environment variables and wipe the cache folder')
-  .option('-y, --yes', 'Automatically confirm prompts')
+  .description(
+    'Reset environment variables and clean up database/cache files (interactive selection)'
+  )
+  .option('-y, --yes', 'Automatically reset using default selections')
   .action(async (options: { yes?: boolean }) => {
     try {
-      console.log('Reset options:', options);
       await resetEnv(options.yes);
     } catch (error) {
       handleError(error);
@@ -681,7 +938,9 @@ env.action(() => {
   console.log('  edit-global           Edit global environment variables');
   console.log('  edit-local            Edit local environment variables');
   console.log('  set-path <path>       Set a custom path for the global environment file');
-  console.log('  reset                 Reset all environment variables and wipe the cache folder');
+  console.log(
+    '  reset                 Reset environment variables and clean up database/cache files (interactive selection)'
+  );
   console.log('  interactive           Start interactive environment variable manager');
   console.log('\nYou can also edit environment variables in the web UI:');
   console.log('  http://localhost:3000/settings');
@@ -731,11 +990,19 @@ async function showMainMenu(yes = false): Promise<void> {
         exit = !returnToMainFromLocal;
         break;
       }
-      case 'set_path':
-        console.info(
-          colors.yellow('\nTo set a custom path, run: elizaos env set-path <path> [--yes]')
-        );
+      case 'set_path': {
+        // Prompt for a path and use the existing setEnvPath function
+        const { path: customPath } = await prompts({
+          type: 'text',
+          name: 'path',
+          message: 'Enter custom path for global environment file:',
+        });
+
+        if (customPath) {
+          await setEnvPath(customPath, yes);
+        }
         break;
+      }
       case 'reset':
         await resetEnv();
         break;
diff --git a/packages/docs/docs/cli/env.md b/packages/docs/docs/cli/env.md
index fc448a29f919e..328a4a33a4494 100644
--- a/packages/docs/docs/cli/env.md
+++ b/packages/docs/docs/cli/env.md
@@ -18,14 +18,14 @@ elizaos env [command] [options]
 
 ## Subcommands
 
-| Subcommand        | Description                                               | Options               |
-| ----------------- | --------------------------------------------------------- | --------------------- |
-| `list`            | List all environment variables                            | `--global`, `--local` |
-| `edit-global`     | Edit global environment variables                         | `-y, --yes`           |
-| `edit-local`      | Edit local environment variables                          | `-y, --yes`           |
-| `reset`           | Reset all environment variables and wipe the cache folder | `-y, --yes`           |
-| `set-path <path>` | Set a custom path for the global environment file         | `-y, --yes`           |
-| `interactive`     | Start interactive environment variable manager            | `-y, --yes`           |
+| Subcommand        | Description                                                   | Options                           |
+| ----------------- | ------------------------------------------------------------- | --------------------------------- |
+| `list`            | List all environment variables                                | `--system`, `--global`, `--local` |
+| `edit-global`     | Edit global environment variables                             | `-y, --yes`                       |
+| `edit-local`      | Edit local environment variables                              | `-y, --yes`                       |
+| `reset`           | Reset environment variables and clean up database/cache files | `-y, --yes`                       |
+| `set-path <path>` | Set a custom path for the global environment file             | `-y, --yes`                       |
+| `interactive`     | Start interactive environment variable manager                | `-y, --yes`                       |
 
 ## Environment Levels
 
@@ -64,6 +64,14 @@ elizaos env list
 
 This will display both global and local variables (if available).
 
+You can also filter the output:
+
+```bash
+elizaos env list --system  # Show only system information
+elizaos env list --global  # Show only global environment variables
+elizaos env list --local   # Show only local environment variables
+```
+
 ### Editing Global Variables
 
 Edit the global environment variables interactively:
@@ -99,20 +107,31 @@ elizaos env set-path /path/to/custom/location
 
 If the specified path is a directory, the command will use `/path/to/custom/location/.env`.
 
-### Resetting Environment Variables
+The command supports tilde expansion, so you can use paths like `~/eliza-config/.env`.
+
+### Resetting Environment Variables and Data
 
-Reset all environment variables and clear the cache:
+Reset environment variables and optionally delete database and cache files:
 
 ```bash
 elizaos env reset
 ```
 
-This will:
+This command provides an interactive selection interface where you can choose which items to reset:
 
-1. Remove the global `.env` file
-2. Clear any custom environment path setting
-3. Wipe the cache folder
-4. Optionally reset the database folder (you'll be prompted)
+- **Global environment variables** - Clears values in global `.env` file while preserving keys
+- **Local environment variables** - Clears values in local `.env` file while preserving keys
+- **Cache folder** - Deletes the cache folder
+- **Global database files** - Deletes global database files (with special handling for PostgreSQL)
+- **Local database files** - Deletes local database files
+
+After selecting items, you'll be shown a summary and asked for confirmation before proceeding.
+
+Use the `-y, --yes` flag to automatically reset using default selections:
+
+```bash
+elizaos env reset --yes
+```
 
 ## Key Variables
 
@@ -148,6 +167,12 @@ elizaos env list
 Output example:
 
 ```
+System Information:
+  Platform: darwin (24.3.0)
+  Architecture: arm64
+  CLI Version: 1.0.0-beta.51
+  Package Manager: bun v1.2.5
+
 Global environment variables (.eliza/.env):
   OPENAI_API_KEY: sk-1234...5678
   MODEL_PROVIDER: openai
@@ -177,6 +202,16 @@ elizaos env edit-global
 elizaos env edit-local
 ```
 
+### Resetting Environment
+
+```bash
+# Interactive reset with selection
+elizaos env reset
+
+# Reset with default selections
+elizaos env reset --yes
+```
+
 ## Related Commands
 
 - [`start`](./start.md): Start your project with the configured environment


Reviews:
user: login: copilot-pull-request-reviewer[bot]
body: ## Pull Request Overview

This PR improves the elizaos environment commands by adding a new --system flag for listing system information and an interactive reset interface that provides fine-grained control over what gets reset. Additionally, the documentation has been updated to reflect these changes alongside enhancements in tilde expansion and error handling for custom environment paths.
- Updated documentation with new flag and interactive selection instructions.
- Enhanced environment command implementation including interactive reset and tilde path expansion.
- Improved error and status messages across commands.

### Reviewed Changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

| File                                      | Description                                                                    |
| ----------------------------------------- | ------------------------------------------------------------------------------ |
| packages/docs/docs/cli/env.md             | Documentation now includes the new --system flag and revised reset instructions.|
| packages/cli/src/commands/env.ts           | Added interactive reset functionality, enhanced flag support, and tilde expansion.|




state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-16T09:32:25Z
user: login: coderabbitai[bot]
body: **Actionable comments posted: 4**

<details>
<summary>🧹 Nitpick comments (1)</summary><blockquote>

<details>
<summary>packages/docs/docs/cli/env.md (1)</summary><blockquote>

`110-111`: **Minor wording tweak for clarity**

“supports tilde expansion” → “supports **`~`** (tilde) expansion” keeps the technical term while highlighting the exact character users need to type.

</blockquote></details>

</blockquote></details>

<details>
<summary>📜 Review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: CHILL**
**Plan: Pro**


<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between 7b4755089da7af180eda974de2471dec8b1fa194 and cfae2d997e55ad8d603bf826c2ea4a721bbc9d7d.

</details>

<details>
<summary>📒 Files selected for processing (2)</summary>

* `packages/cli/src/commands/env.ts` (8 hunks)
* `packages/docs/docs/cli/env.md` (5 hunks)

</details>

<details>
<summary>🧰 Additional context used</summary>

<details>
<summary>🪛 Biome (1.9.4)</summary>

<details>
<summary>packages/cli/src/commands/env.ts</summary>

[error] 668-670: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.

The declaration is defined in this switch clause:

Unsafe fix: Wrap the declaration in a block.


(lint/correctness/noSwitchDeclarations)

---

[error] 993-999: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.

The declaration is defined in this switch clause:

Unsafe fix: Wrap the declaration in a block.


(lint/correctness/noSwitchDeclarations)

</details>

</details>

</details>

<details>
<summary>⏰ Context from checks skipped due to timeout of 90000ms (3)</summary>

* GitHub Check: test
* GitHub Check: databaseIntegrationTests
* GitHub Check: integration-tests

</details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-16T09:34:56Z

Review comments:
diff_hunk: @@ -418,75 +437,288 @@ async function addNewVariable(envPath: string, envVars: Record<string, string>):
 }
 
 /**
- * Reset all environment variables and wipe the cache folder
+ * Helper function to reset an environment file by keeping keys but clearing values
+ * @param filePath Path to the environment file
+ * @returns A boolean indicating success/failure
  */
-async function resetEnv(yes = false): Promise<void> {
-  console.log('resetEnv called with yes =', yes);
-  let confirm = true;
-  if (!yes) {
-    const resp = await prompts({
-      type: 'confirm',
-      name: 'confirm',
-      message:
-        'This will delete all environment variables and wipe the cache folder. Are you sure?',
-      initial: false,
-    });
-    confirm = resp.confirm;
+async function resetEnvFile(filePath: string): Promise<boolean> {
+  try {
+    if (!existsSync(filePath)) {
+      return false;
+    }
+
+    const envVars = await parseEnvFile(filePath);
+    if (Object.keys(envVars).length === 0) {
+      return false; // No variables to reset
+    }
+
+    const resetVars = Object.keys(envVars).reduce(
+      (acc, key) => {
+        acc[key] = '';
+        return acc;
+      },
+      {} as Record<string, string>
+    );
+
+    await writeEnvFile(filePath, resetVars);
+    return true;
+  } catch (error) {
+    console.error(`Error resetting environment file at ${filePath}: ${error.message}`);
+    return false;
   }
-  if (!confirm) {
-    console.log('Reset cancelled.');
-    return;
+}
+
+// Reset operation types and helper functions
+type ResetTarget = 'globalEnv' | 'localEnv' | 'cache' | 'globalDb' | 'localDb';
+type ResetAction = 'reset' | 'deleted' | 'skipped' | 'warning';
+
+interface ResetItem {
+  title: string;
+  value: ResetTarget;
+  description?: string;
+  selected?: boolean;
+}
+
+/**
+ * Delete a directory with error handling
+ * @param dir Directory path to delete
+ * @param actions Action log collection to update
+ * @param label Description label for this operation
+ * @returns Success or failure
+ */
+async function safeDeleteDirectory(
+  dir: string,
+  actions: Record<string, string[]>,
+  label: string
+): Promise<boolean> {
+  if (!existsSync(dir)) {
+    actions.skipped.push(`${label} (not found)`);
+    return false;
   }
 
-  // Get paths
+  try {
+    await rimraf(dir);
+    if (!existsSync(dir)) {
+      actions.deleted.push(label);
+      return true;
+    } else {
+      actions.warnings.push(`Failed to delete ${label.toLowerCase()}`);
+      return false;
+    }
+  } catch (error) {
+    actions.warnings.push(`Failed to delete ${label.toLowerCase()}: ${error.message}`);
+    return false;
+  }
+}
+
+/**
+ * Reset environment variables and selected folders
+ */
+async function resetEnv(yes = false): Promise<void> {
+  // Get all relevant paths
   const homeDir = os.homedir();
   const elizaDir = path.join(homeDir, '.eliza');
   const globalEnvPath = await getGlobalEnvPath();
   const cacheDir = path.join(elizaDir, 'cache');
-  const dbDir = path.join(elizaDir, 'projects', stringToUuid(process.cwd()), 'db');
+  const projectUuid = stringToUuid(process.cwd());
+  const globalDbDir = path.join(elizaDir, 'projects', projectUuid, 'db');
+  const globalPgliteDir = path.join(elizaDir, 'projects', projectUuid, 'pglite');
+  const localEnvPath = path.join(process.cwd(), '.env');
+  const localDbDir = path.join(process.cwd(), 'elizadb');
 
-  // Remove global .env file
-  if (existsSync(globalEnvPath)) {
-    await fs.unlink(globalEnvPath);
-    console.log('Removed global .env file');
+  // Check if external Postgres is in use
+  let usingExternalPostgres = false;
+  try {
+    const globalEnvVars = await parseEnvFile(globalEnvPath);
+    const localEnvVars = await parseEnvFile(localEnvPath);
+    usingExternalPostgres =
+      (globalEnvVars.POSTGRES_URL && globalEnvVars.POSTGRES_URL.trim() !== '') ||
+      (localEnvVars.POSTGRES_URL && localEnvVars.POSTGRES_URL.trim() !== '');
+  } catch (error) {
+    // Ignore errors
   }
 
-  // Clear custom env path if set
-  if (existsSync(CONFIG_FILE)) {
-    try {
-      const content = await fs.readFile(CONFIG_FILE, 'utf-8');
-      const config = JSON.parse(content);
+  // Create reset item options
+  const resetItems: ResetItem[] = [
+    {
+      title: 'Global environment variables',
+      value: 'globalEnv',
+      description: 'Reset values in global .env file',
+      selected: false,
+    },
+    {
+      title: 'Local environment variables',
+      value: 'localEnv',
+      description: 'Reset values in local .env file',
+      selected: false,
+    },
+    {
+      title: 'Cache folder',
+      value: 'cache',
+      description: existsSync(cacheDir)
+        ? 'Delete the cache folder'
+        : 'Cache folder not found, nothing to delete',
+      selected: false,
+    },
+    {
+      title: 'Global database files',
+      value: 'globalDb',
+      description:
+        !existsSync(globalDbDir) && !existsSync(globalPgliteDir)
+          ? 'Global database files not found, nothing to delete'
+          : usingExternalPostgres
+            ? 'WARNING: External PostgreSQL database detected - only local files will be removed'
+            : 'Delete global database files',
+      selected: false,
+    },
+    {
+      title: 'Local database files',
+      value: 'localDb',
+      description: existsSync(localDbDir)
+        ? 'Delete local database files'
+        : 'Local database folder not found, nothing to delete',
+      selected: false,
+    },
+  ];
+
+  // Get selected items (from options or defaults)
+  let selectedValues: ResetTarget[] = [];
+
+  if (yes) {
path: packages/cli/src/commands/env.ts
user: login: Copilot
body: When the --yes flag is used, the default resetItems all have selected set to false; as a result, selectedValues will be empty and no reset occurs. Consider setting appropriate default selections for the --yes branch or explicitly documenting this behavior.
created_at: 2025-05-16T09:32:25Z
author_association: CONTRIBUTOR
diff_hunk: @@ -495,6 +727,11 @@ async function resetEnv(yes = false): Promise<void> {
  * @param autoConfirm Automatically confirm prompts
  */
 async function setEnvPath(customPath: string, autoConfirm = false): Promise<void> {
+  // Expand tilde (~) in the path if present
+  if (customPath.startsWith('~')) {
+    customPath = path.join(os.homedir(), customPath.substring(1));
+  }
+
path: packages/cli/src/commands/env.ts
user: login: coderabbitai[bot]
body: _⚠️ Potential issue_

**Fix tilde (`~`) expansion bug in custom path resolution**

`path.join(os.homedir(), customPath.substring(1))` discards the home directory when `substring(1)` begins with `/`, producing paths like `/.eliza` instead of `/home/alice/.eliza`.

```diff
-  if (customPath.startsWith('~')) {
-    customPath = path.join(os.homedir(), customPath.substring(1));
-  }
+  if (customPath === '~') {
+    customPath = os.homedir();
+  } else if (customPath.startsWith('~/')) {
+    customPath = path.join(os.homedir(), customPath.slice(2));
+  }
```

This preserves the intended `$HOME` prefix for both `~` and `~/…` inputs.

<details>
<summary>🤖 Prompt for AI Agents</summary>

```
In packages/cli/src/commands/env.ts around lines 730 to 734, the current tilde
expansion using path.join(os.homedir(), customPath.substring(1)) incorrectly
removes the home directory slash when the substring starts with '/'. To fix
this, replace the path.join call with a concatenation that preserves the slash
after the home directory, ensuring that both '~' and '~/...' inputs correctly
expand to the full home directory path.
```

</details>

<!-- This is an auto-generated comment by CodeRabbit -->
created_at: 2025-05-16T09:34:56Z
author_association: CONTRIBUTOR
diff_hunk: @@ -732,9 +989,16 @@
         break;
       }
       case 'set_path':
-        console.info(
-          colors.yellow('\nTo set a custom path, run: elizaos env set-path <path> [--yes]')
-        );
+        // Prompt for a path and use the existing setEnvPath function
+        const { path: customPath } = await prompts({
+          type: 'text',
+          name: 'path',
+          message: 'Enter custom path for global environment file:',
+        });
+
+        if (customPath) {
+          await setEnvPath(customPath, yes);
+        }
path: packages/cli/src/commands/env.ts
user: login: coderabbitai[bot]
body: _⚠️ Potential issue_

**Isolate `const { path: customPath }` declaration inside `switch`**

Same `switch`-scoping issue as above; wrap the `set_path` case in braces to prevent the binding from being visible to the following cases.

```diff
-      case 'set_path':
+      case 'set_path': {
         const { path: customPath } = await prompts({ … });
         …
         break;
+      }
```



<!-- suggestion_start -->

<details>
<summary>📝 Committable suggestion</summary>

> ‼️ **IMPORTANT**
> Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

```suggestion
      case 'set_path': {
        const { path: customPath } = await prompts({
          type: 'text',
          name: 'path',
          message: 'Enter custom path for global environment file:',
        });

        if (customPath) {
          await setEnvPath(customPath, yes);
        }
        break;
      }
```

</details>

<!-- suggestion_end -->

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 Biome (1.9.4)</summary>

[error] 993-999: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.

The declaration is defined in this switch clause:

Unsafe fix: Wrap the declaration in a block.


(lint/correctness/noSwitchDeclarations)

</details>

</details>

<details>
<summary>🤖 Prompt for AI Agents</summary>

```
In packages/cli/src/commands/env.ts around lines 993 to 1001, the declaration of
const { path: customPath } is currently outside the switch case block, causing
its scope to leak into subsequent cases. To fix this, wrap the entire set_path
case code, including the prompts call and the if statement, inside braces {} to
isolate the customPath variable within that case block and prevent scope
leakage.
```

</details>

<!-- This is an auto-generated comment by CodeRabbit -->
created_at: 2025-05-16T09:34:56Z
author_association: CONTRIBUTOR
diff_hunk: @@ -418,75 +437,288 @@
 }
 
 /**
- * Reset all environment variables and wipe the cache folder
+ * Helper function to reset an environment file by keeping keys but clearing values
+ * @param filePath Path to the environment file
+ * @returns A boolean indicating success/failure
  */
-async function resetEnv(yes = false): Promise<void> {
-  console.log('resetEnv called with yes =', yes);
-  let confirm = true;
-  if (!yes) {
-    const resp = await prompts({
-      type: 'confirm',
-      name: 'confirm',
-      message:
-        'This will delete all environment variables and wipe the cache folder. Are you sure?',
-      initial: false,
-    });
-    confirm = resp.confirm;
+async function resetEnvFile(filePath: string): Promise<boolean> {
+  try {
+    if (!existsSync(filePath)) {
+      return false;
+    }
+
+    const envVars = await parseEnvFile(filePath);
+    if (Object.keys(envVars).length === 0) {
+      return false; // No variables to reset
+    }
+
+    const resetVars = Object.keys(envVars).reduce(
+      (acc, key) => {
+        acc[key] = '';
+        return acc;
+      },
+      {} as Record<string, string>
+    );
+
+    await writeEnvFile(filePath, resetVars);
+    return true;
+  } catch (error) {
+    console.error(`Error resetting environment file at ${filePath}: ${error.message}`);
+    return false;
   }
-  if (!confirm) {
-    console.log('Reset cancelled.');
-    return;
+}
+
+// Reset operation types and helper functions
+type ResetTarget = 'globalEnv' | 'localEnv' | 'cache' | 'globalDb' | 'localDb';
+type ResetAction = 'reset' | 'deleted' | 'skipped' | 'warning';
+
+interface ResetItem {
+  title: string;
+  value: ResetTarget;
+  description?: string;
+  selected?: boolean;
+}
+
+/**
+ * Delete a directory with error handling
+ * @param dir Directory path to delete
+ * @param actions Action log collection to update
+ * @param label Description label for this operation
+ * @returns Success or failure
+ */
+async function safeDeleteDirectory(
+  dir: string,
+  actions: Record<string, string[]>,
+  label: string
+): Promise<boolean> {
+  if (!existsSync(dir)) {
+    actions.skipped.push(`${label} (not found)`);
+    return false;
   }
 
-  // Get paths
+  try {
+    await rimraf(dir);
+    if (!existsSync(dir)) {
+      actions.deleted.push(label);
+      return true;
+    } else {
+      actions.warnings.push(`Failed to delete ${label.toLowerCase()}`);
+      return false;
+    }
+  } catch (error) {
+    actions.warnings.push(`Failed to delete ${label.toLowerCase()}: ${error.message}`);
+    return false;
+  }
+}
+
+/**
+ * Reset environment variables and selected folders
+ */
+async function resetEnv(yes = false): Promise<void> {
+  // Get all relevant paths
   const homeDir = os.homedir();
   const elizaDir = path.join(homeDir, '.eliza');
   const globalEnvPath = await getGlobalEnvPath();
   const cacheDir = path.join(elizaDir, 'cache');
-  const dbDir = path.join(elizaDir, 'projects', stringToUuid(process.cwd()), 'db');
+  const projectUuid = stringToUuid(process.cwd());
+  const globalDbDir = path.join(elizaDir, 'projects', projectUuid, 'db');
+  const globalPgliteDir = path.join(elizaDir, 'projects', projectUuid, 'pglite');
+  const localEnvPath = path.join(process.cwd(), '.env');
+  const localDbDir = path.join(process.cwd(), 'elizadb');
 
-  // Remove global .env file
-  if (existsSync(globalEnvPath)) {
-    await fs.unlink(globalEnvPath);
-    console.log('Removed global .env file');
+  // Check if external Postgres is in use
+  let usingExternalPostgres = false;
+  try {
+    const globalEnvVars = await parseEnvFile(globalEnvPath);
+    const localEnvVars = await parseEnvFile(localEnvPath);
+    usingExternalPostgres =
+      (globalEnvVars.POSTGRES_URL && globalEnvVars.POSTGRES_URL.trim() !== '') ||
+      (localEnvVars.POSTGRES_URL && localEnvVars.POSTGRES_URL.trim() !== '');
+  } catch (error) {
+    // Ignore errors
   }
 
-  // Clear custom env path if set
-  if (existsSync(CONFIG_FILE)) {
-    try {
-      const content = await fs.readFile(CONFIG_FILE, 'utf-8');
-      const config = JSON.parse(content);
+  // Create reset item options
+  const resetItems: ResetItem[] = [
+    {
+      title: 'Global environment variables',
+      value: 'globalEnv',
+      description: 'Reset values in global .env file',
+      selected: false,
+    },
+    {
+      title: 'Local environment variables',
+      value: 'localEnv',
+      description: 'Reset values in local .env file',
+      selected: false,
+    },
+    {
+      title: 'Cache folder',
+      value: 'cache',
+      description: existsSync(cacheDir)
+        ? 'Delete the cache folder'
+        : 'Cache folder not found, nothing to delete',
+      selected: false,
+    },
+    {
+      title: 'Global database files',
+      value: 'globalDb',
+      description:
+        !existsSync(globalDbDir) && !existsSync(globalPgliteDir)
+          ? 'Global database files not found, nothing to delete'
+          : usingExternalPostgres
+            ? 'WARNING: External PostgreSQL database detected - only local files will be removed'
+            : 'Delete global database files',
+      selected: false,
+    },
+    {
+      title: 'Local database files',
+      value: 'localDb',
+      description: existsSync(localDbDir)
+        ? 'Delete local database files'
+        : 'Local database folder not found, nothing to delete',
+      selected: false,
+    },
+  ];
+
+  // Get selected items (from options or defaults)
+  let selectedValues: ResetTarget[] = [];
+
+  if (yes) {
+    // Use default selections if using --yes flag
+    selectedValues = resetItems.filter((item) => item.selected).map((item) => item.value);
+  } else {
+    // Prompt user to select items with styling matching interactive mode
+    const { selections } = await prompts({
+      type: 'multiselect',
+      name: 'selections',
+      message: colors.cyan(colors.bold('Select items to reset:')),
+      choices: resetItems,
+      instructions: false,
+      hint: '- Space to select, Enter to confirm',
+      min: 1,
+    });
 
-      if (config.envPath) {
-        const { envPath, ...restConfig } = config;
-        await fs.writeFile(CONFIG_FILE, JSON.stringify(restConfig, null, 2));
-        console.log('Cleared custom environment path setting');
-      }
-    } catch (error) {
-      console.error(`Error clearing custom env path: ${error.message}`);
+    if (!selections || selections.length === 0) {
+      console.log('No items selected. Reset cancelled.');
+      return;
+    }
+
+    selectedValues = selections;
+
+    // Show selected items
+    console.log('\nYou selected:');
+    for (const value of selectedValues) {
+      const item = resetItems.find((item) => item.value === value);
+      console.log(`  • ${item.title}`);
+    }
+
+    // Final confirmation
+    const { confirm } = await prompts({
+      type: 'confirm',
+      name: 'confirm',
+      message: 'Are you sure you want to reset the selected items?',
+      initial: false,
+    });
+
+    if (!confirm) {
+      console.log('Reset cancelled.');
+      return;
+    }
+  }
+
+  // Track reset results
+  const actions: Record<ResetAction, string[]> = {
+    reset: [],
+    deleted: [],
+    skipped: [],
+    warning: [],
+  };
+
+  // Process each selected item
+  for (const target of selectedValues) {
+    switch (target) {
+      case 'globalEnv':
+        if (await resetEnvFile(globalEnvPath)) {
+          actions.reset.push('Global environment variables');
+        } else {
+          actions.skipped.push('Global environment variables (no file or empty)');
+        }
+        break;
+
+      case 'localEnv':
+        if (await resetEnvFile(localEnvPath)) {
+          actions.reset.push('Local environment variables');
+        } else {
+          actions.skipped.push('Local environment variables (no file or empty)');
+        }
+        break;
+
+      case 'cache':
+        await safeDeleteDirectory(cacheDir, actions, 'Cache folder');
+        break;
+
+      case 'globalDb':
+        if (usingExternalPostgres) {
+          actions.warning.push(
+            'External PostgreSQL database detected. Database data cannot be reset but local database cache files will be removed.'
+          );
+        }
+
+        let anyGlobalDbDeleted = false;
+
+        // Try deleting db dir
+        if (existsSync(globalDbDir)) {
+          if (await safeDeleteDirectory(globalDbDir, actions, 'Global database folder')) {
+            anyGlobalDbDeleted = true;
+          }
+        }
+
+        // Try deleting PGLite dir
+        if (existsSync(globalPgliteDir)) {
+          if (
+            await safeDeleteDirectory(globalPgliteDir, actions, 'Global PGLite database folder')
+          ) {
+            anyGlobalDbDeleted = true;
+          }
+        }
+
+        // If neither existed and nothing was deleted
path: packages/cli/src/commands/env.ts
user: login: coderabbitai[bot]
body: _⚠️ Potential issue_

**Avoid leaking `let` declarations across `switch` cases**

Declaring `let anyGlobalDbDeleted = false;` directly inside a `case` shares it with all other cases, violating `noSwitchDeclarations` and risking accidental reuse.

Wrap the case body in its own block:

```diff
-      case 'globalDb':
+      case 'globalDb': {
         …
         let anyGlobalDbDeleted = false;
         …
         break;
+      }
```

Apply the same pattern to any other case that introduces `const`/`let` bindings.  



<!-- suggestion_start -->

<details>
<summary>📝 Committable suggestion</summary>

> ‼️ **IMPORTANT**
> Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

```suggestion
      case 'globalDb': {
        let anyGlobalDbDeleted = false;

        // Try deleting db dir
        if (existsSync(globalDbDir)) {
          if (await safeDeleteDirectory(globalDbDir, actions, 'Global database folder')) {
            anyGlobalDbDeleted = true;
          }
        }

        // Try deleting PGLite dir
        if (existsSync(globalPgliteDir)) {
          if (
            await safeDeleteDirectory(globalPgliteDir, actions, 'Global PGLite database folder')
          ) {
            anyGlobalDbDeleted = true;
          }
        }

        // If neither existed and nothing was deleted
        break;
      }
```

</details>

<!-- suggestion_end -->

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 Biome (1.9.4)</summary>

[error] 668-670: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.

The declaration is defined in this switch clause:

Unsafe fix: Wrap the declaration in a block.


(lint/correctness/noSwitchDeclarations)

</details>

</details>

<details>
<summary>🤖 Prompt for AI Agents</summary>

```
In packages/cli/src/commands/env.ts around lines 668 to 686, the variable
anyGlobalDbDeleted is declared with let inside a switch case, which causes it to
be shared across cases and violates noSwitchDeclarations. To fix this, wrap the
entire case block where anyGlobalDbDeleted is declared and used inside curly
braces {} to create a new block scope. Apply this block scoping pattern to any
other switch cases that declare const or let variables to prevent scope leakage.
```

</details>

<!-- This is an auto-generated comment by CodeRabbit -->
created_at: 2025-05-16T09:34:56Z
author_association: CONTRIBUTOR
diff_hunk: @@ -418,75 +437,288 @@
 }
 
 /**
- * Reset all environment variables and wipe the cache folder
+ * Helper function to reset an environment file by keeping keys but clearing values
+ * @param filePath Path to the environment file
+ * @returns A boolean indicating success/failure
  */
-async function resetEnv(yes = false): Promise<void> {
-  console.log('resetEnv called with yes =', yes);
-  let confirm = true;
-  if (!yes) {
-    const resp = await prompts({
-      type: 'confirm',
-      name: 'confirm',
-      message:
-        'This will delete all environment variables and wipe the cache folder. Are you sure?',
-      initial: false,
-    });
-    confirm = resp.confirm;
+async function resetEnvFile(filePath: string): Promise<boolean> {
+  try {
+    if (!existsSync(filePath)) {
+      return false;
+    }
+
+    const envVars = await parseEnvFile(filePath);
+    if (Object.keys(envVars).length === 0) {
+      return false; // No variables to reset
+    }
+
+    const resetVars = Object.keys(envVars).reduce(
+      (acc, key) => {
+        acc[key] = '';
+        return acc;
+      },
+      {} as Record<string, string>
+    );
+
+    await writeEnvFile(filePath, resetVars);
+    return true;
+  } catch (error) {
+    console.error(`Error resetting environment file at ${filePath}: ${error.message}`);
+    return false;
   }
-  if (!confirm) {
-    console.log('Reset cancelled.');
-    return;
+}
+
+// Reset operation types and helper functions
+type ResetTarget = 'globalEnv' | 'localEnv' | 'cache' | 'globalDb' | 'localDb';
+type ResetAction = 'reset' | 'deleted' | 'skipped' | 'warning';
+
+interface ResetItem {
+  title: string;
+  value: ResetTarget;
+  description?: string;
+  selected?: boolean;
+}
+
+/**
+ * Delete a directory with error handling
+ * @param dir Directory path to delete
+ * @param actions Action log collection to update
+ * @param label Description label for this operation
+ * @returns Success or failure
+ */
+async function safeDeleteDirectory(
+  dir: string,
+  actions: Record<string, string[]>,
+  label: string
+): Promise<boolean> {
+  if (!existsSync(dir)) {
+    actions.skipped.push(`${label} (not found)`);
+    return false;
   }
 
-  // Get paths
+  try {
+    await rimraf(dir);
+    if (!existsSync(dir)) {
+      actions.deleted.push(label);
+      return true;
+    } else {
+      actions.warnings.push(`Failed to delete ${label.toLowerCase()}`);
+      return false;
+    }
+  } catch (error) {
+    actions.warnings.push(`Failed to delete ${label.toLowerCase()}: ${error.message}`);
+    return false;
+  }
+}
+
+/**
+ * Reset environment variables and selected folders
+ */
+async function resetEnv(yes = false): Promise<void> {
+  // Get all relevant paths
   const homeDir = os.homedir();
   const elizaDir = path.join(homeDir, '.eliza');
   const globalEnvPath = await getGlobalEnvPath();
   const cacheDir = path.join(elizaDir, 'cache');
-  const dbDir = path.join(elizaDir, 'projects', stringToUuid(process.cwd()), 'db');
+  const projectUuid = stringToUuid(process.cwd());
+  const globalDbDir = path.join(elizaDir, 'projects', projectUuid, 'db');
+  const globalPgliteDir = path.join(elizaDir, 'projects', projectUuid, 'pglite');
+  const localEnvPath = path.join(process.cwd(), '.env');
+  const localDbDir = path.join(process.cwd(), 'elizadb');
 
-  // Remove global .env file
-  if (existsSync(globalEnvPath)) {
-    await fs.unlink(globalEnvPath);
-    console.log('Removed global .env file');
+  // Check if external Postgres is in use
+  let usingExternalPostgres = false;
+  try {
+    const globalEnvVars = await parseEnvFile(globalEnvPath);
+    const localEnvVars = await parseEnvFile(localEnvPath);
+    usingExternalPostgres =
+      (globalEnvVars.POSTGRES_URL && globalEnvVars.POSTGRES_URL.trim() !== '') ||
+      (localEnvVars.POSTGRES_URL && localEnvVars.POSTGRES_URL.trim() !== '');
+  } catch (error) {
+    // Ignore errors
   }
 
-  // Clear custom env path if set
-  if (existsSync(CONFIG_FILE)) {
-    try {
-      const content = await fs.readFile(CONFIG_FILE, 'utf-8');
-      const config = JSON.parse(content);
+  // Create reset item options
+  const resetItems: ResetItem[] = [
+    {
+      title: 'Global environment variables',
+      value: 'globalEnv',
+      description: 'Reset values in global .env file',
+      selected: false,
+    },
+    {
+      title: 'Local environment variables',
+      value: 'localEnv',
+      description: 'Reset values in local .env file',
+      selected: false,
+    },
+    {
+      title: 'Cache folder',
+      value: 'cache',
+      description: existsSync(cacheDir)
+        ? 'Delete the cache folder'
+        : 'Cache folder not found, nothing to delete',
+      selected: false,
+    },
+    {
+      title: 'Global database files',
+      value: 'globalDb',
+      description:
+        !existsSync(globalDbDir) && !existsSync(globalPgliteDir)
+          ? 'Global database files not found, nothing to delete'
+          : usingExternalPostgres
+            ? 'WARNING: External PostgreSQL database detected - only local files will be removed'
+            : 'Delete global database files',
+      selected: false,
+    },
+    {
+      title: 'Local database files',
+      value: 'localDb',
+      description: existsSync(localDbDir)
+        ? 'Delete local database files'
+        : 'Local database folder not found, nothing to delete',
+      selected: false,
+    },
+  ];
+
+  // Get selected items (from options or defaults)
+  let selectedValues: ResetTarget[] = [];
+
+  if (yes) {
+    // Use default selections if using --yes flag
+    selectedValues = resetItems.filter((item) => item.selected).map((item) => item.value);
+  } else {
path: packages/cli/src/commands/env.ts
user: login: coderabbitai[bot]
body: _⚠️ Potential issue_

**`--yes` flag currently resets *nothing***  

When `--yes` is supplied you filter by `item.selected`, yet all `selected` flags default to `false`, resulting in an empty `selectedValues` array and therefore a no-op reset.

```diff
-  if (yes) {
-    selectedValues = resetItems.filter((item) => item.selected).map((item) => item.value);
+  if (yes) {
+    // By default pick every item when running non-interactively
+    selectedValues = resetItems.map((item) => item.value);
   } else {
```

Without this change, CI scripts invoking `elizaos env reset --yes` will silently do nothing.

<details>
<summary>🤖 Prompt for AI Agents</summary>

```
In packages/cli/src/commands/env.ts around lines 585 to 590, the code filters
resetItems by item.selected when the --yes flag is used, but all selected flags
default to false, causing selectedValues to be empty and no reset to occur. To
fix this, modify the logic so that when --yes is true, selectedValues includes
all resetItems' values regardless of their selected flag, ensuring the reset
operation actually affects all intended items.
```

</details>

<!-- This is an auto-generated comment by CodeRabbit -->
created_at: 2025-05-16T09:34:56Z
author_association: CONTRIBUTOR

PR comments:
user: login: coderabbitai[bot]
created_at: 2025-05-16T09:31:52Z
body: <!-- This is an auto-generated comment: summarize by coderabbit.ai -->
<!-- This is an auto-generated comment: skip review by coderabbit.ai -->

> [!IMPORTANT]
> ## Review skipped
> 
> Auto reviews are disabled on this repository.
> 
> Please check the settings in the CodeRabbit UI or the `.coderabbit.yaml` file in this repository. To trigger a single review, invoke the `@coderabbitai review` command.
> 
> You can disable this status message by setting the `reviews.review_status` to `false` in the CodeRabbit configuration file.

<!-- end of auto-generated comment: skip review by coderabbit.ai -->
<!-- walkthrough_start -->

## Walkthrough

This update refactors the CLI's environment variable management, introducing interactive and more robust handling for listing, resetting, and setting environment variables and related files. It enhances user guidance, error handling, and interactivity, and updates both command descriptions and documentation to reflect these changes.

## Changes

| File(s)                                                      | Change Summary                                                                                                                                                                                                                                  |
|--------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `packages/cli/src/commands/env.ts`                           | Refactored environment reset logic for interactivity and granularity; added helpers for safe directory deletion and env file resetting; improved listing to always show local section with guidance; expanded set path handling and error checks; updated command descriptions and options. |
| `packages/docs/docs/cli/env.md`                              | Updated documentation to reflect new interactive reset behavior, expanded command options, clarified usage, added examples, and improved output descriptions.                                                                                    |

## Sequence Diagram(s)

```mermaid
sequenceDiagram
    participant User
    participant CLI
    participant FileSystem

    User->>CLI: Run 'env reset' command
    CLI-->>User: Display interactive selection (env files, cache, db)
    User->>CLI: Select items to reset
    CLI->>FileSystem: Reset selected env files (clear values, keep keys)
    CLI->>FileSystem: Delete selected directories (cache/db)
    FileSystem-->>CLI: Report actions (reset, deleted, skipped)
    CLI-->>User: Show summary of performed actions
```

## Possibly related PRs

- elizaOS/eliza#4423: Refactors environment reset logic in the same file, directly affecting how environment and database directories are handled.

## Suggested reviewers

- wtfsayo

## Poem

> In the CLI’s garden, fresh changes bloom,  
> Env resets now dance in an interactive room.  
> Guidance abounds if your .env is astray,  
> With prompts and safe deletes to light the way.  
> Tilde expands, errors handled with care—  
> ElizaOS, your envs are debonair!  
> 🌱✨

<!-- walkthrough_end -->
<!-- internal state start -->


<!-- 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= -->

<!-- internal state end -->
<!-- tips_start -->

---

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.

<details>
<summary>❤️ Share</summary>

- [X](https://twitter.com/intent/tweet?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A&url=https%3A//coderabbit.ai)
- [Mastodon](https://mastodon.social/share?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A%20https%3A%2F%2Fcoderabbit.ai)
- [Reddit](https://www.reddit.com/submit?title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&text=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code.%20Check%20it%20out%3A%20https%3A//coderabbit.ai)
- [LinkedIn](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fcoderabbit.ai&mini=true&title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&summary=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code)

</details>

<details>
<summary>🪧 Tips</summary>

### Chat

There are 3 ways to chat with [CodeRabbit](https://coderabbit.ai?utm_source=oss&utm_medium=github&utm_campaign=elizaOS/eliza&utm_content=4610):

- Review comments: Directly reply to a review comment made by CodeRabbit. Example:
  - `I pushed a fix in commit <commit_id>, please review it.`
  - `Explain this complex logic.`
  - `Open a follow-up GitHub issue for this discussion.`
- Files and specific lines of code (under the "Files changed" tab): Tag `@coderabbitai` in a new review comment at the desired location with your query. Examples:
  - `@coderabbitai explain this code block.`
  -	`@coderabbitai modularize this function.`
- PR comments: Tag `@coderabbitai` in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
  - `@coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.`
  - `@coderabbitai read src/utils.ts and explain its main purpose.`
  - `@coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.`
  - `@coderabbitai help me debug CodeRabbit configuration file.`

### Support

Need help? Create a ticket on our [support page](https://www.coderabbit.ai/contact-us/support) for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

### CodeRabbit Commands (Invoked using PR comments)

- `@coderabbitai pause` to pause the reviews on a PR.
- `@coderabbitai resume` to resume the paused reviews.
- `@coderabbitai review` to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
- `@coderabbitai full review` to do a full review from scratch and review all the files again.
- `@coderabbitai summary` to regenerate the summary of the PR.
- `@coderabbitai generate docstrings` to [generate docstrings](https://docs.coderabbit.ai/finishing-touches/docstrings) for this PR.
- `@coderabbitai generate sequence diagram` to generate a sequence diagram of the changes in this PR.
- `@coderabbitai resolve` resolve all the CodeRabbit review comments.
- `@coderabbitai configuration` to show the current CodeRabbit configuration for the repository.
- `@coderabbitai help` to get help.

### Other keywords and placeholders

- Add `@coderabbitai ignore` anywhere in the PR description to prevent this PR from being reviewed.
- Add `@coderabbitai summary` to generate the high-level summary at a specific location in the PR description.
- Add `@coderabbitai` anywhere in the PR title to generate the title automatically.

### CodeRabbit Configuration File (`.coderabbit.yaml`)

- You can programmatically configure CodeRabbit by adding a `.coderabbit.yaml` file to the root of your repository.
- Please see the [configuration documentation](https://docs.coderabbit.ai/guides/configure-coderabbit) for more information.
- If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: `# yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json`

### Documentation and Community

- Visit our [Documentation](https://docs.coderabbit.ai) for detailed information on how to use CodeRabbit.
- Join our [Discord Community](http://discord.gg/coderabbit) to get help, request features, and share feedback.
- Follow us on [X/Twitter](https://twitter.com/coderabbitai) for updates and announcements.

</details>

<!-- tips_end -->
author_association: CONTRIBUTOR
user: login: yungalgo
created_at: 2025-05-16T09:31:55Z
body: @coderabbitai review
author_association: CONTRIBUTOR
user: login: coderabbitai[bot]
created_at: 2025-05-16T09:32:01Z
body: <!-- This is an auto-generated reply by CodeRabbit -->
<details>
<summary>✅ Actions performed</summary>

Review triggered.

> Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

</details>
author_association: CONTRIBUTOR
user: login: coderabbitai[bot]
created_at: 2025-05-16T09:32:14Z
body: <!-- This is an auto-generated reply by CodeRabbit -->
<details>
<summary>✅ Actions performed</summary>

Review triggered.

> Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

</details>
author_association: CONTRIBUTOR