mise-environment-management

$npx mdskill add TheBushidoCollective/han/mise-environment-management

Manage project-specific environment variables and settings using Mise for consistent execution.

  • Configure environment variables, paths, and settings specific to a project directory.
  • Integrates with shell environments (Bash, Zsh) and uses TOML configuration files.
  • Determines necessary context by reading and writing project configuration files.
  • Activates the required environment or executes commands within the defined scope.

SKILL.md

.github/skills/mise-environment-managementView on GitHub ↗
---
name: mise-environment-management
user-invocable: false
description: Use when managing environment variables and project settings with Mise. Covers env configuration, direnv replacement, and per-directory settings.
allowed-tools:
  - Read
  - Write
  - Edit
  - Bash
  - Grep
  - Glob
---

# Mise - Environment Management

Managing environment variables, project settings, and directory-specific configuration with Mise.

## Basic Environment Variables

### Defining Environment Variables

```toml
# mise.toml
[env]
NODE_ENV = "production"
DATABASE_URL = "postgresql://localhost/myapp"
API_KEY = "development-key"
LOG_LEVEL = "info"
```

### Loading Environment

```bash
# Activate mise environment
mise activate bash  # Or zsh, fish

# Or use mise exec
mise exec -- node app.js

# Or mise run
mise run start
```

## Advanced Environment Configuration

### Template Variables

```toml
[env]
PROJECT_ROOT = "{{ config_root }}"
DATA_DIR = "{{ config_root }}/data"
LOG_FILE = "{{ config_root }}/logs/app.log"
```

### Environment File Loading

```toml
[env]
_.file = ".env"
_.file = [".env", ".env.local"]
```

### Conditional Environment Variables

```toml
[env]
# Set based on other variables
DATABASE_URL = "postgresql://{{ env.DB_HOST | default(value='localhost') }}/{{ env.DB_NAME }}"
```

## Path Management

### Adding to PATH

```toml
[env]
_.path = [
  "{{ config_root }}/bin",
  "{{ config_root }}/scripts",
  "/usr/local/bin"
]
```

### Library Paths

```toml
[env]
LD_LIBRARY_PATH = "{{ config_root }}/lib:$LD_LIBRARY_PATH"
DYLD_LIBRARY_PATH = "{{ config_root }}/lib:$DYLD_LIBRARY_PATH"
```

## Tool-Specific Environments

### Python Virtual Environment

```toml
[tools]
python = "3.12"

[env]
_.python.venv = { path = ".venv", create = true }
VIRTUAL_ENV = "{{ config_root }}/.venv"
```

### Node.js Environment

```toml
[tools]
node = "20.10.0"

[env]
NODE_ENV = "development"
NODE_OPTIONS = "--max-old-space-size=4096"
NPM_CONFIG_PREFIX = "{{ config_root }}/.npm-global"
```

### Go Environment

```toml
[tools]
go = "1.21"

[env]
GOPATH = "{{ config_root }}/.go"
GOBIN = "{{ config_root }}/.go/bin"
GO111MODULE = "on"
```

## Replacing direnv

### Basic direnv Replacement

```toml
# Instead of .envrc
# export DATABASE_URL=postgresql://localhost/myapp
# export NODE_ENV=development

# Use mise.toml
[env]
DATABASE_URL = "postgresql://localhost/myapp"
NODE_ENV = "development"
```

### Allowed Directories

```toml
# mise.toml - mark as trusted
[settings]
experimental_monorepo_root = true  # Trust subdirectories
```

### Watch File Changes

Mise automatically reloads when mise.toml changes, similar to direnv.

## Hierarchical Configuration

### Global Settings

```toml
# ~/.config/mise/config.toml
[env]
EDITOR = "code"
GIT_AUTHOR_NAME = "Your Name"
GIT_AUTHOR_EMAIL = "you@example.com"
```

### Project Settings

```toml
# ~/projects/myapp/mise.toml
[env]
PROJECT_NAME = "myapp"
DATABASE_URL = "postgresql://localhost/myapp"
```

### Local Overrides

```toml
# ~/projects/myapp/mise.local.toml (gitignored)
[env]
DATABASE_URL = "postgresql://localhost/myapp-dev"
DEBUG = "true"
```

## Sensitive Data

### Environment Files

```toml
# mise.toml
[env]
_.file = ".env.local"  # Gitignored file with secrets
```

```bash
# .env.local (add to .gitignore)
API_KEY=secret-key-here
DATABASE_PASSWORD=secret-password
```

### Using System Environment

```toml
[env]
# Reference existing environment variables
API_KEY = "$API_KEY"
DATABASE_URL = "$DATABASE_URL"
```

### Secure Secrets Management

```bash
# Don't commit secrets to mise.toml
# Instead, reference from external secret managers

# Example with 1Password CLI
mise exec -- op run -- node app.js

# Or load from encrypted file
mise exec -- sops exec-env .env.encrypted -- node app.js
```

## Mise Environment Variables

### Built-in Variables

Mise provides these variables automatically:

```bash
$MISE_ORIGINAL_CWD      # Directory where mise was invoked
$MISE_CONFIG_ROOT       # Directory containing mise.toml
$MISE_PROJECT_ROOT      # Project root directory
$MISE_DATA_DIR          # Mise data directory
$MISE_CACHE_DIR         # Mise cache directory
```

### Using in Configuration

```toml
[env]
PROJECT_ROOT = "{{ env.MISE_PROJECT_ROOT }}"
CONFIG_FILE = "{{ env.MISE_CONFIG_ROOT }}/config.yaml"
```

## Configuration Validation

### Check Current Environment

```bash
# Show current environment
mise env

# Show specific variable
mise env DATABASE_URL

# Export as shell commands
mise env -s bash > .env.sh
source .env.sh
```

### Verify Configuration

```bash
# Check loaded config files
mise config

# Show resolved settings
mise settings
```

## Best Practices

### Separate Public and Private Config

```toml
# mise.toml (committed)
[env]
NODE_ENV = "development"
LOG_LEVEL = "info"
API_URL = "https://api.example.com"

# mise.local.toml (gitignored)
[env]
API_KEY = "secret-key"
DATABASE_PASSWORD = "secret-password"
```

### Use Descriptive Variable Names

```toml
# Good: Clear, descriptive names
[env]
DATABASE_CONNECTION_POOL_SIZE = "10"
API_REQUEST_TIMEOUT_MS = "5000"
FEATURE_FLAG_NEW_UI = "true"

# Avoid: Vague abbreviations
[env]
DB_POOL = "10"
TIMEOUT = "5000"
FLAG = "true"
```

### Document Required Variables

```toml
# mise.toml
[env]
# Database configuration (required)
DATABASE_URL = "postgresql://localhost/myapp"

# API keys (set in mise.local.toml)
# API_KEY = "your-key-here"

# Optional feature flags
FEATURE_ANALYTICS = "false"
```

### Use Templates for Paths

```toml
# Good: Relative to config root
[env]
DATA_DIR = "{{ config_root }}/data"
LOGS_DIR = "{{ config_root }}/logs"

# Avoid: Hardcoded paths
[env]
DATA_DIR = "/Users/me/project/data"
```

## Common Patterns

### Multi-Environment Setup

```toml
# mise.toml - base configuration
[env]
APP_NAME = "myapp"
LOG_FORMAT = "json"

# mise.development.toml
[env]
NODE_ENV = "development"
DEBUG = "true"
DATABASE_URL = "postgresql://localhost/myapp_dev"

# mise.production.toml
[env]
NODE_ENV = "production"
DEBUG = "false"
DATABASE_URL = "postgresql://prod-server/myapp"
```

```bash
# Switch environments
ln -sf mise.development.toml mise.local.toml
# Or
ln -sf mise.production.toml mise.local.toml
```

### Database Configuration

```toml
[env]
DATABASE_HOST = "localhost"
DATABASE_PORT = "5432"
DATABASE_NAME = "myapp"
DATABASE_USER = "postgres"
DATABASE_URL = "postgresql://{{ env.DATABASE_USER }}:{{ env.DATABASE_PASSWORD }}@{{ env.DATABASE_HOST }}:{{ env.DATABASE_PORT }}/{{ env.DATABASE_NAME }}"
```

### Feature Flags

```toml
[env]
# Feature toggles
FEATURE_NEW_DASHBOARD = "true"
FEATURE_BETA_API = "false"
FEATURE_EXPERIMENTAL_CACHE = "true"

# Feature rollout percentages
FEATURE_NEW_CHECKOUT_ROLLOUT = "25"
```

### CI/CD Environment

```toml
# mise.toml
[env]
NODE_ENV = "{{ env.CI | default(value='development') }}"
SKIP_PREFLIGHT_CHECK = "{{ env.CI | default(value='false') }}"
```

## Anti-Patterns

### Don't Commit Secrets

```toml
# Bad: Secrets in committed file
[env]
API_KEY = "sk-secret-key-12345"
DATABASE_PASSWORD = "password123"

# Good: Reference from secure location
[env]
_.file = ".env.local"  # Gitignored
```

### Don't Duplicate Global Config

```toml
# Bad: Repeating global settings in every project
# ~/project-a/mise.toml
[env]
EDITOR = "code"
GIT_AUTHOR_NAME = "Your Name"

# ~/project-b/mise.toml
[env]
EDITOR = "code"
GIT_AUTHOR_NAME = "Your Name"

# Good: Use global config
# ~/.config/mise/config.toml
[env]
EDITOR = "code"
GIT_AUTHOR_NAME = "Your Name"
```

### Don't Hardcode Environment Names

```toml
# Bad: Hardcoded check
[tasks.deploy]
run = '''
if [ "$NODE_ENV" = "production" ]; then
  ./deploy-prod.sh
fi
'''

# Good: Use configuration
[tasks.deploy]
env = { DEPLOYMENT_TARGET = "production" }
run = "./deploy.sh"
```

## Advanced Patterns

### Dynamic Environment Loading

```toml
[env]
# Load environment based on git branch
BRANCH = "{{ exec(command='git branch --show-current') }}"
DEPLOY_ENV = "{{ env.BRANCH | replace(from='main', to='production') | replace(from='develop', to='staging') }}"
```

### Computed Variables

```toml
[env]
PROJECT_NAME = "myapp"
NAMESPACE = "{{ env.PROJECT_NAME }}-{{ env.ENVIRONMENT }}"
REDIS_URL = "redis://{{ env.NAMESPACE }}-redis:6379"
```

### Environment Inheritance

```toml
# Base configuration
[env]
LOG_LEVEL = "info"
CACHE_TTL = "3600"

# Override in specific contexts
[env.production]
LOG_LEVEL = "warn"
CACHE_TTL = "7200"
```

## Related Skills

- **task-configuration**: Using environment variables in tasks
- **tool-management**: Tool-specific environment configuration

More from TheBushidoCollective/han

SkillDescription
absinthe-resolversUse when implementing GraphQL resolvers with Absinthe. Covers resolver patterns, dataloader integration, batching, and error handling.
absinthe-schemaUse when designing GraphQL schemas with Absinthe. Covers type definitions, interfaces, unions, enums, and schema organization patterns.
absinthe-subscriptionsUse when implementing real-time GraphQL subscriptions with Absinthe. Covers Phoenix channels, PubSub, and subscription patterns.
act-docker-setupUse when configuring Docker environments for act, selecting runner images, managing container resources, or troubleshooting Docker-related issues with local GitHub Actions testing.
act-local-testingUse when testing GitHub Actions workflows locally with act. Covers act CLI usage, Docker configuration, debugging workflows, and troubleshooting common issues when running workflows on your local machine.
act-workflow-syntaxUse when creating or modifying GitHub Actions workflow files. Provides guidance on workflow syntax, triggers, jobs, steps, and expressions for creating valid GitHub Actions workflows that can be tested locally with act.
ameba-configurationUse when configuring Ameba rules and settings for Crystal projects including .ameba.yml setup, rule management, severity levels, and code quality enforcement.
ameba-custom-rulesUse when creating custom Ameba rules for Crystal code analysis including rule development, AST traversal, issue reporting, and rule testing.
ameba-integrationUse when integrating Ameba into development workflows including CI/CD pipelines, pre-commit hooks, GitHub Actions, and automated code review processes.
analyze-performanceAnalyze performance metrics and identify slow transactions in Sentry