Skip to content
mise-configuration logo

mise Configuration as Single Source of Truth

mise-configuration

Configure environment via mise [env] SSoT. TRIGGERS - mise env, mise.toml, environment variables, centralize config, Python venv, mise templates.

SKILL.md

Full skill instructions

mise Configuration as Single Source of Truth

Use mise [env] as centralized configuration with backward-compatible defaults.

Core Principle

Define all configurable values in .mise.toml [env] section. Scripts read via environment variables with fallback defaults. Same code path works WITH or WITHOUT mise installed.

Key insight: mise auto-loads [env] values when shell has mise activate configured. Scripts using os.environ.get("VAR", "default") pattern work identically whether mise is present or not.

Quick Reference

Language Patterns

LanguagePatternNotes
Pythonos.environ.get("VAR", "default")Returns string, cast if int
Bash${VAR:-default}Standard POSIX expansion
JavaScriptprocess.env.VAR || "default"Falsy check, watch for "0"
Goos.Getenv("VAR") with defaultEmpty string if unset
Ruststd::env::var("VAR").unwrap_or()Returns Result<String>

Special Directives

DirectivePurposeExample
_.fileLoad from .env files_.file = ".env"
_.pathExtend PATH_.path = ["bin", "node_modules/​.bin"]
_.sourceExecute bash scripts_.source = "./​scripts/​env.sh"
_.python.venvAuto-create Python venv_.python.venv = { path = ".venv", create = true }

Python Venv Auto-Creation (Critical)

Auto-create and activate Python virtual environments:

[env]
_.python.venv = { path = ".venv", create = true }

This pattern is used in ALL projects. When entering the directory with mise activated:

  1. Creates .venv if it doesn't exist
  2. Activates the venv automatically
  3. Works with uv for fast venv creation

Alternative via [settings]:

[settings]
python.uv_venv_auto = true

Special Directives

Load from .env Files (_.file)

[env]
# Single file
_.file = ".env"

# Multiple files with options
_.file = [
    ".env",
    { path = ".env.secrets", redact = true }
]

Extend PATH (_.path)

[env]
_.path = [
    "{{config_root}}/​bin",
    "{{config_root}}/​node_modules/​.bin",
    "scripts"
]

Source Bash Scripts (_.source)

[env]
_.source = "./​scripts/​env.sh"
_.source = { path = ".secrets.sh", redact = true }

Lazy Evaluation (tools = true)

By default, env vars resolve BEFORE tools install. Use tools = true to access tool-generated paths:

[env]
# Access PATH after tools are set up
GEM_BIN = { value = "{{env.GEM_HOME}}/​bin", tools = true }

# Load .env files after tool setup
_.file = { path = ".env", tools = true }

Template Syntax (Tera)

mise uses Tera templating. Delimiters: {{ }} expressions, {% %} statements, {# #} comments.

Built-in Variables

VariableDescription
{{config_root}}Directory containing .mise.toml
{{cwd}}Current working directory
{{env.VAR}}Environment variable
{{mise_bin}}Path to mise binary
{{mise_pid}}mise process ID
{{xdg_cache_home}}XDG cache directory
{{xdg_config_home}}XDG config directory
{{xdg_data_home}}XDG data directory

Functions

[env]
# Get env var with fallback
NODE_VER = "{{ get_env(name='NODE_VERSION', default='20') }}"

# Execute shell command
TIMESTAMP = "{{ exec(command='date +%Y-%m-%d') }}"

# System info
ARCH = "{{ arch() }}"      # x64, arm64
OS = "{{ os() }}"          # linux, macos, windows
CPUS = "{{ num_cpus() }}"

# File operations
VERSION = "{{ read_file(path='VERSION') | trim }}"
HASH = "{{ hash_file(path='config.json', len=8) }}"

Filters

[env]
# Case conversion
SNAKE = "{{ name | snakecase }}"
KEBAB = "{{ name | kebabcase }}"
CAMEL = "{{ name | lowercamelcase }}"

# String manipulation
TRIMMED = "{{ text | trim }}"
UPPER = "{{ text | upper }}"
REPLACED = "{{ text | replace(from='old', to='new') }}"

# Path operations
ABSOLUTE = "{{ path | absolute }}"
BASENAME = "{{ path | basename }}"
DIRNAME = "{{ path | dirname }}"

Conditionals

[env]
{% if env.DEBUG %}
LOG_LEVEL = "debug"
{% else %}
LOG_LEVEL = "info"
{% endif %}

Required & Redacted Variables

Required Variables

Enforce variable definition with helpful messages:

[env]
DATABASE_URL = { required = true }
API_KEY = { required = "Get from https://example.com/​api-keys" }

Redacted Variables

Hide sensitive values from output:

[env]
SECRET = { value = "my_secret", redact = true }
_.file = { path = ".env.secrets", redact = true }

# Pattern-based redactions
redactions = ["*_TOKEN", "*_KEY", "PASSWORD"]

[settings] Section

[settings]
experimental = true              # Enable experimental features
python.uv_venv_auto = true       # Auto-create venv with uv

[tools] Version Pinning

Pin tool versions for reproducibility:

[tools]
python = "3.11"  # minimum baseline; use 3.12, 3.13 as needed
node = "latest"
uv = "latest"

# With options
rust = { version = "1.75", profile = "minimal" }

min_version: Enforce mise version compatibility:

min_version = "2024.9.5"

Implementation Steps

  1. Identify hardcoded values - timeouts, paths, thresholds, feature flags
  2. Create .mise.toml - add [env] section with documented variables
  3. Add venv auto-creation - _.python.venv = { path = ".venv", create = true }
  4. Update scripts - use env vars with original values as defaults
  5. Add ADR reference - comment: # ADR: 2025-12-08-mise-env-centralized-config
  6. Test without mise - verify script works using defaults
  7. Test with mise - verify activated shell uses .mise.toml values

GitHub Token Multi-Account Patterns (MANDATORY for Multi-Account Setups) {#github-token-multi-account-patterns}

For multi-account GitHub setups, mise [env] provides per-directory token configuration that overrides gh CLI's global authentication.

Token Storage

Store tokens in a centralized, secure location:

mkdir -p ~/​.claude/​.secrets
chmod 700 ~/​.claude/​.secrets

# Create token files (one per account)
gh auth login  # authenticate as account
gh auth token > ~/​.claude/​.secrets/​gh-token-accountname
chmod 600 ~/​.claude/​.secrets/​gh-token-*

Per-Directory Configuration

# ~/​.claude/​.mise.toml (terrylica account)
[env]
GH_TOKEN = "{{ read_file(path=config_root ~ '/​.secrets/​gh-token-terrylica') | trim }}"
GITHUB_TOKEN = "{{ read_file(path=config_root ~ '/​.secrets/​gh-token-terrylica') | trim }}"
GH_ACCOUNT = "terrylica"  # For human reference only
# ~/​eon/​.mise.toml (terrylica account - different directory)
[env]
GH_TOKEN = "{{ read_file(path=env.HOME ~ '/​.claude/​.secrets/​gh-token-terrylica') | trim }}"
GITHUB_TOKEN = "{{ read_file(path=env.HOME ~ '/​.claude/​.secrets/​gh-token-terrylica') | trim }}"
GH_ACCOUNT = "terrylica"

Variable Naming Convention

VariableUsage ContextExample
GH_TOKENmise [env], Doppler, verification tasks.mise.toml, shell scripts
GITHUB_TOKENnpm scripts, GitHub Actions, semantic-releasepackage.json, workflows

Rule: Always set BOTH variables in mise [env] pointing to the same token file. Different tools check different variable names.

Alternative: 1Password Integration

For enhanced security with automatic token rotation:

[env]
GH_TOKEN = "{{ op_read('op://Engineering/​GitHub Token/​credential') }}"

With caching for performance:

[env]
GH_TOKEN = "{{ cache(key='gh_token', duration='1h', run='op read op://Engineering/​GitHub Token/​credential') }}"

Verification

/​usr/​bin/​env bash << 'MISE_EOF'
for dir in ~/​.claude ~/​eon ~/​own ~/​scripts ~/​459ecs; do
  cd "$dir" && eval "$(mise hook-env -s bash)" && echo "$dir → $GH_ACCOUNT"
done
MISE_EOF

ADR Reference: GitHub Multi-Account Authentication

SSH ControlMaster Warning: If using multi-account SSH, ensure ControlMaster no is set for GitHub hosts in ~/​.ssh/​config. Cached connections can authenticate with the wrong account. See semantic-release authentication for troubleshooting.

Anti-Patterns

Anti-PatternWhyInstead
mise exec -- script.pyForces mise dependencyUse env vars with defaults
Secrets in .mise.tomlVisible in repoUse Doppler or redact = true
No defaults in scriptsBreaks without miseAlways provide fallback
Mixing env/​tools resolutionOrder mattersUse tools = true for tool-dependent vars

Task Orchestration Integration

When you detect workflow opportunities during mise configuration, prescriptively invoke the mise-tasks skill.

Detection Triggers

  • Multi-step workflows (test + build + deploy)
  • Repeatable project commands (lint, format, release)
  • Dependency chains (db-migrate depends on db-init)
  • File-tracked builds (sources/​outputs caching)

Prescriptive AI Reminder

PRESCRIPTIVE: When detecting multi-step project workflows, invoke mise-tasks skill to generate appropriate [tasks] definitions with dependency management.

Example: From Environment to Tasks

Step 1: Configure environment (this skill):

[env]
DATABASE_URL = "postgresql://localhost/​mydb"
_.python.venv = { path = ".venv", create = true }

Step 2: Define tasks (mise-tasks skill):

[tasks.test]
depends = ["lint"]
run = "pytest tests/"

[tasks.deploy]
depends = ["test", "build"]
run = "deploy.sh"

Tasks automatically inherit [env] values.


Additional Resources

For complete code patterns and examples, see: references/​patterns.md

For task orchestration, see: mise-tasks skill - Dependencies, arguments, file tracking, watch mode

ADR Reference: When implementing mise configuration, create an ADR at docs/​adr/​YYYY-MM-DD-mise-env-centralized-config.md in your project.

More skills from majiayu000

xiaohongshu logo
majiayu000/claude-arsenal

xiaohongshu

xiaohongshu

286 148
View
agent-task-conductor logo
majiayu000/claude-skill-registry

agent-task-conductor

Conduct multi-agent task orchestration and workflow coordination.

663 1
View
conductor-setup logo
majiayu000/claude-skill-registry

conductor-setup

Initialize project with Conductor artifacts (product definition,

663 1
View
animation-designer logo
majiayu000/claude-skill-registry

animation-designer

Expert in web animations, transitions, and motion design using Framer Motion and CSS

663 1
View
diagramming logo
majiayu000/claude-skill-registry

diagramming

Creates Mermaid and ASCII diagrams for flowcharts, architecture, ERDs, state machines, mindmaps, and more. Use when user mentions diagram, flowchart, mermaid, ASCII diagram, text diagram, terminal diagram, visualize, C4, mindmap, architecture diagram, sequence diagram, ERD, or needs visual docume...

663 1
View
h3-pg logo
majiayu000/claude-skill-registry-data

h3-pg

PostgreSQL bindings for H3 hexagonal grid system. Use when working with H3 cells in Postgres, including spatial indexing, geometry/geography integration, and raster analysis.

23 1
View
conductor-development logo
majiayu000/claude-skill-registry

conductor-development

Context-Driven Development skill for projects using Conductor. Use this skill when you detect a `conductor/` directory in the project, when working on tasks defined in a `plan.md` file, or when the user asks about tracks, specs, or plans. Automatically applies TDD workflow, tracks task completion...

663 1
View
conductor-status logo
majiayu000/claude-skill-registry

conductor-status

Display project status, active tracks, and next actions

663 1
View
dockerization logo
majiayu000/claude-skill-registry

dockerization

Official Stakpak application containerization standard operating procedure, a step-by-step guidline to properly dockerize applications. This is a rule book curated by the Stakpak Team.

663 1
View

Popular AI tools

Kaiber logo
Video

Kaiber

Generate, edit, and beat-sync AI video with leading models in one workspace.

Paid
View
Vimcal logo
Productivity

Vimcal

The world's fastest calendar for remote work

Free
View

Transform Your Design with AI Designer by ImgCreator.ai

Freemium
View
Akool AI logo
Content & writing

Akool AI

Revolutionizing Video Production with AI-Powered Creativity

Paid
View

Extend an image past the frame and let AI fill the new aspect ratio.

Freemium
View
StarByFace logo
Security

StarByFace

Discover your celebrity doppelgänger with StarByFace!

Free
View
C

ChainClarity explains 700+ crypto whitepapers in plain English, with layered summaries, comparisons, research tools, alerts, and a $4.99 Pro plan.

Freemium
View
Opus Clip logo
Coding & apps

Opus Clip

Opus.ai: Revolutionize Your Web Experience

Free
View