Claude-skill-inception tauri-dotenv-working-directory

install
source · Clone the upstream repo
git clone https://github.com/strataga/claude-skill-inception
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/strataga/claude-skill-inception "$T" && mkdir -p ~/.claude/skills && cp -r "$T/tauri-dotenv-working-directory" ~/.claude/skills/strataga-claude-skill-inception-tauri-dotenv-working-directory && rm -rf "$T"
manifest: tauri-dotenv-working-directory/SKILL.md
source content

Tauri Dotenvy Working Directory Fix

Problem

When adding

dotenvy
to a Tauri app to load environment variables, relative paths like
../../.env
fail because the working directory during
cargo tauri dev
is not what you'd expect from the file structure.

Context / Trigger Conditions

Error symptoms:

  • GHOST_URL not set
    or similar "env var not set" errors
  • GhostClient::from_env()
    or API clients fail to initialize
  • dotenvy::from_filename("../../.env")
    returns Err
  • App works when env vars are exported manually but not via .env

Project structure:

project-root/
├── .env                 # Environment file here
├── Cargo.toml
├── crates/
└── ui/
    ├── src/
    └── src-tauri/
        ├── Cargo.toml
        └── src/
            └── main.rs  # dotenvy loaded here

Assumption (wrong): Since

main.rs
is in
ui/src-tauri/src/
, you might think CWD is
ui/src-tauri/
and use
../../.env
to reach the project root.

Reality: When

cargo tauri dev
runs, the working directory is the project root, not
ui/src-tauri/
. So the path should just be
.env
.

Solution

Try multiple paths to handle different execution contexts:

fn main() {
    // Load .env file - try multiple locations
    // When running via `cargo tauri dev`, CWD is project root
    // When running the binary directly, CWD varies
    let env_paths = [
        ".env",                    // Project root (cargo tauri dev)
        "../../.env",              // From ui/src-tauri (if run directly)
        "../.env",                 // From ui/ (if run from there)
    ];

    let mut loaded = false;
    for path in &env_paths {
        if dotenvy::from_filename(path).is_ok() {
            eprintln!("Loaded .env from: {}", path);
            loaded = true;
            break;
        }
    }

    if !loaded {
        eprintln!("Warning: Could not load .env file from any location");
    }

    tauri::Builder::default()
        // ... rest of setup
}

Cargo.toml dependency:

[dependencies]
dotenvy = "0.15"

Verification

  1. Add logging to see which path works:

    eprintln!("Loaded .env from: {}", path);
    
  2. Check the Tauri dev output for the message:

    Loaded .env from: .env
    
  3. Verify env vars are available:

    println!("GHOST_URL = {:?}", std::env::var("GHOST_URL"));
    

Example

Before (fails):

fn main() {
    // Wrong - assumes CWD is ui/src-tauri
    if let Err(e) = dotenvy::from_filename("../../.env") {
        eprintln!("Warning: Could not load .env: {}", e);
    }
    // ...
}

After (works):

fn main() {
    // Correct - CWD is project root during cargo tauri dev
    if let Err(e) = dotenvy::from_filename(".env") {
        eprintln!("Warning: Could not load .env: {}", e);
    }
    // ...
}

Notes

  • The working directory behavior is determined by how Tauri's dev command runs cargo
  • In production builds, the working directory may be different (app installation dir)
  • For production, consider embedding secrets differently or using a config file
  • The multi-path approach handles both dev and various execution scenarios
  • Always log which path was loaded to aid debugging

Related

  • Tauri doesn't automatically load .env files - you must add dotenvy yourself
  • This issue is separate from Tauri IPC (which only works in the webview)
  • Environment variables set in the shell will override .env file values