Skip to content

bicf/managenv

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

9 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

managenv

A tool to manage multiple .env files by combining reusable fragments into artifacts.

Installation

# System-wide (user install, recommended)
pip install --user .
# or
uv pip install --user .

This installs the managenv command to ~/.local/bin/. Make sure ~/.local/bin is on your PATH.

Alternatively, install system-wide (requires root) or run directly with python managenv.py.


Quick Start

1. Create fragments in fragments/:

# fragments/backend.env
API_HOST=localhost
API_PORT=8000

# fragments/frontend.env
VITE_API_URL=http://localhost:8000

2. Configure managenv.json:

{
  "fragments": {
    "backend": {"uri": "file://fragments/backend.env"},
    "frontend": {"uri": "file://fragments/frontend.env"}
  },
  "artifacts": {
    "dev.env": ["backend", "frontend"]
  }
}

3. Generate:

managenv
# Generated: artifacts/dev.env

Commands

Generate All Artifacts

managenv

Generates all artifacts defined in the config.

Generate Specific Artifacts

managenv -a dev.env

Generates only the specified artifact.

Multiple artifacts (repeatable flag or comma-separated):

managenv -a dev.env -a prod.env
managenv dev.env,prod.env

Dry Run (Preview)

managenv --dry-run

Shows what would be generated without writing files.

List Configuration

managenv --list

Displays all fragments and artifacts defined in the config.

Validate Configuration

managenv --validate

Checks for missing files and undefined fragment references.

Show Diff

managenv --diff dev.env

Shows what would change compared to existing artifact files.

Multiple artifacts:

managenv --diff dev.env --diff prod.env
managenv --diff dev.env,prod.env

Add Artifact

managenv --add dev.env backend,frontend

Adds a new artifact definition to the config. Optionally specify a custom deployment path:

managenv --add prod.env backend.prod --uri file:///var/www/app/.env

Use --deploy to generate the artifact immediately after adding:

managenv --add dev.env backend,frontend --deploy

Delete Artifact

managenv --delete dev.env

Removes an artifact definition from the config.

Import Existing Env File

managenv --import existing.env --prefix backend

Imports an existing .env file as a new fragment. Auto-creates config if needed.

Initialize Config

managenv --init

Creates a new managenv-config.json with default structure.

Shell Completion

Auto-install to rc file:

# Install to ~/.bashrc
managenv --scripts bash --apply

# Install to ~/.zshrc
managenv --scripts zsh --apply

Running --apply again is safe — it detects if completions are already installed.

Save to file (manual):

# Generate bash completion
managenv --scripts bash > ~/.managenv-completion.bash
echo 'source ~/.managenv-completion.bash' >> ~/.bashrc

# Generate zsh completion
managenv --scripts zsh > ~/.managenv-completion.zsh
echo 'source ~/.managenv-completion.zsh' >> ~/.zshrc

Load directly in current shell:

# Bash
source <(./managenv.py --scripts bash)

# Zsh
source <(./managenv.py --scripts zsh)

Provides intelligent completion for artifact names, fragment names, and flags.

Custom Config File

managenv -c /path/to/config.json

Uses a custom config file. The base directory (used to resolve relative paths) is always the directory containing the config file.

Default config location (searched in order):

  1. Path specified with -c/--config flag
  2. managenv.json in script directory (if exists)
  3. managenv.json in current working directory

Features

Fragments

Fragments are small .env snippets that can be combined. Each fragment is defined with a URI.

Config:

{
  "fragments": {
    "database": {"uri": "file://fragments/database.env"},
    "cache": {"uri": "file://fragments/cache.env"}
  }
}

Fragment file (fragments/database.env):

DB_HOST=localhost
DB_PORT=5432
DB_NAME=myapp

Artifacts

Artifacts are the generated output files. They combine one or more fragments.

Brief format (array of fragment aliases):

{
  "artifacts": {
    "dev.env": ["database", "cache"]
  }
}

This saves to artifacts/dev.env by default.

Full format (with custom deployment path):

{
  "artifacts": {
    "dev.env": {
      "fragments": ["database", "cache"],
      "deployment": "file:///home/user/project/.env"
    }
  }
}

This saves to the specified absolute path.


Auto-Inheritance (Dot Notation)

Use dot notation to create inheritance chains. When you reference database.prod, it automatically includes database first, then applies database.prod overrides.

Config:

{
  "fragments": {
    "database": {"uri": "file://fragments/database.env"},
    "database.prod": {"uri": "file://fragments/database.prod.env"}
  },
  "artifacts": {
    "production.env": ["database.prod"]
  }
}

Fragments:

# fragments/database.env
DB_HOST=localhost
DB_PORT=5432

# fragments/database.prod.env
DB_HOST=prod.rds.amazonaws.com

Result (artifacts/production.env):

DB_HOST=prod.rds.amazonaws.com
DB_PORT=5432

The database.prod reference automatically includes database first, then overrides DB_HOST.


URI Formats

Fragments can be loaded from various sources.

Relative path (both formats work):

{"uri": "fragments/backend.env"}
{"uri": "file://fragments/backend.env"}

Absolute path:

{"uri": "/etc/shared/common.env"}
{"uri": "file:///etc/shared/common.env"}

URL (read-only):

{"uri": "https://config.example.com/base.env"}

URL content is cached during each run.


Deployment Paths

Control where artifacts are saved using the deployment property.

Default (saves to artifacts/ folder):

{
  "artifacts": {
    "dev.env": ["backend", "frontend"]
  }
}

Saves to: artifacts/dev.env

Relative path:

{
  "artifacts": {
    "dev.env": {
      "fragments": ["backend"],
      "deployment": "file://output/dev.env"
    }
  }
}

Saves to: output/dev.env (relative to config)

Absolute path:

{
  "artifacts": {
    "production.env": {
      "fragments": ["backend.prod"],
      "deployment": "file:///var/www/app/.env"
    }
  }
}

Saves to: /var/www/app/.env


Remote Deployment (SSH/Rsync)

Deploy artifacts to remote servers using ssh:// or rsync:// URIs. The tool uses your existing SSH and rsync configuration (.ssh/config, keys, etc.).

SSH deployment:

{
  "artifacts": {
    "production.env": {
      "fragments": ["backend.prod"],
      "deployment": "ssh://prod-server/var/www/app/.env"
    }
  }
}

Uses scp to copy the file to the remote server.

Rsync deployment:

{
  "artifacts": {
    "staging.env": {
      "fragments": ["backend.staging"],
      "deployment": "rsync://staging/home/deploy/.env"
    }
  }
}

Uses rsync -az to sync the file to the remote server.

URI format:

URI Host Remote Path
ssh://myserver/var/www/.env myserver /var/www/.env
ssh://user@host/path/.env user@host /path/.env
rsync://backup/data/.env backup /data/.env

Error handling:

By default, remote deployment failures cause the tool to exit immediately. Set exit_on_fail to false to continue with other artifacts:

{
  "artifacts": {
    "staging.env": {
      "fragments": ["backend.staging"],
      "deployment": "rsync://staging/home/deploy/.env",
      "exit_on_fail": false
    }
  }
}

Note: The artifact is always saved locally to artifacts/<name> first, then deployed to the remote location.


Import Existing Files

Convert existing .env files into fragments.

managenv --import /path/to/existing.env --prefix backend

This:

  1. Reads the existing file
  2. Removes variables already defined in parent fragments (if any)
  3. Saves unique variables to fragments/backend.env
  4. Adds the fragment to your config

With inheritance:

# First import the base
managenv --import base.env --prefix database

# Then import prod (removes inherited vars automatically)
managenv --import prod.env --prefix database.prod

Directory Structure

All relative paths in the config are resolved from the config file's directory (the base directory).

project/
├── managenv.json          # Configuration (base directory = project/)
├── fragments/             # Your .env fragments (relative to config)
│   ├── backend.env
│   ├── backend.prod.env
│   └── frontend.env
├── artifacts/             # Generated .env files (default location)
│   ├── dev.env
│   └── production.env
└── history/               # Automatic backups before overwrite

Example with custom config location:

/home/user/configs/app.json   # Config file (base directory = /home/user/configs/)
/home/user/configs/fragments/ # Fragments resolved from config directory
/home/user/configs/artifacts/ # Artifacts resolved from config directory

Complete Example

Config (managenv-config.json):

{
  "fragments": {
    "backend": {"uri": "file://fragments/backend.env"},
    "backend.prod": {"uri": "file://fragments/backend.prod.env"},
    "frontend": {"uri": "file://fragments/frontend.env"},
    "frontend.prod": {"uri": "file://fragments/frontend.prod.env"}
  },
  "artifacts": {
    "dev.env": ["backend", "frontend"],
    "production.env": {
      "fragments": ["backend.prod", "frontend.prod"],
      "deployment": "file:///var/www/app/.env"
    }
  }
}

Generate:

managenv
# Generated: artifacts/dev.env
# Generated: /var/www/app/.env

About

managenv is a Python tool for merging `.env` snippet files into output files with automatic inheritance via dot notation.

Resources

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages