Skip to content

Add .env file support#167

Open
sudoish wants to merge 13 commits into
joerdav:mainfrom
sudoish:main
Open

Add .env file support#167
sudoish wants to merge 13 commits into
joerdav:mainfrom
sudoish:main

Conversation

@sudoish
Copy link
Copy Markdown

@sudoish sudoish commented Apr 5, 2026

Summary

Adds .env file support to xc, resolving #162.

Changes

  • Load .env and .env.local files at startup (before task parsing)
  • CLI flags:
    • --env-file <path> to load a custom env file
    • --no-env to skip loading .env files
  • Security: Skip files with world-readable or group-readable permissions (Unix only)
  • Documentation: Complete README section with examples and usage
  • Tests: Full test coverage for dotenv package

Implementation Details

Load Order

Environment variables are loaded in this order (later overrides earlier):

  1. System environment
  2. .env file
  3. .env.local file
  4. Task-level Env: statements
  5. CLI input values
  6. Inline export statements

Files Added

  • internal/dotenv/ - New package for .env loading
    • loader.go - Core implementation with security checks
    • loader_test.go - Full test coverage
  • .env.example - Template file for users

Files Modified

  • cmd/xc/main.go - Integration and CLI flags
  • README.md - Complete documentation section
  • .gitignore - Added .env patterns

Design Decisions

  • Global load at startup: Simple, predictable, matches ecosystem patterns (docker-compose, npm)
  • .env.local override: Standard pattern for local secrets (git-ignored)
  • Security first: Permission checks prevent accidental secret exposure
  • Graceful degradation: Missing files don't error, malformed files warn and continue
  • Backward compatible: Existing task-level Env: statements still work

Testing

All tests passing:

$ go test ./...
ok  	github.com/joerdav/xc/cmd/xc
ok  	github.com/joerdav/xc/internal/dotenv
ok  	github.com/joerdav/xc/parser/parsemd
ok  	github.com/joerdav/xc/parser/parseorg
ok  	github.com/joerdav/xc/run

Manual testing completed:

  • ✅ .env loads automatically
  • ✅ .env.local overrides .env
  • ✅ --no-env skips loading
  • ✅ --env-file loads custom file
  • ✅ World-readable files show warning
  • ✅ Task-level Env still works

Example Usage

Before (cluttered task definition):

## deploy

Env: DATABASE_URL=postgres://prod/db, API_KEY=secret, ENV=production

\```
./deploy.sh
\```

After (with .env):

## deploy

\```
./deploy.sh
\```

With .env:

DATABASE_URL=postgres://prod/db
API_KEY=secret
ENV=production

And .env.local for local overrides:

DATABASE_URL=postgres://localhost/db
ENV=development

Breaking Changes

None. This is fully backward compatible.

Checklist

  • Tests pass
  • Documentation updated
  • Backward compatible
  • Security considerations addressed
  • Example files provided

Closes #162

@sudoish sudoish requested a review from joerdav as a code owner April 5, 2026 19:15
@sudoish sudoish marked this pull request as draft April 5, 2026 19:18
@sudoish sudoish marked this pull request as ready for review April 6, 2026 02:06
@nashidau
Copy link
Copy Markdown

I realised this would probably supersede #171 as well.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Feature request: add .env file support

2 participants