Files
codex/prs/bolinfest/study/PR-1653-study.md
2025-09-02 15:17:45 -07:00

3.0 KiB
Raw Blame History

Dotenv Support: Practical Guide (PR #1653)

DOs

  • Load Early: Call load_dotenv() before creating any threads or the Tokio runtime.
    // binary/lib entry point
    codex_common::dotenv::load_dotenv();
    let rt = tokio::runtime::Runtime::new()?;
    rt.block_on(async_main());
    
  • Support Both Locations: Load from ~/.codex/.env (via CODEX_HOME) and the current directorys .env.
    pub fn load_dotenv() {
        if let Ok(codex_home) = codex_core::config::find_codex_home() {
            dotenvy::from_path(codex_home.join(".env")).ok();
        }
        dotenvy::dotenv().ok();
    }
    
  • Reuse Core Logic: Use codex_core::config::find_codex_home() (now pub) instead of duplicating path logic.
    let env_path = codex_core::config::find_codex_home()?.join(".env");
    dotenvy::from_path(env_path).ok();
    
  • Feature-Gate for CLI: Expose the helper only when the cli feature is enabled and depend on it from CLI-facing crates.
    # codex-rs/linux-sandbox/Cargo.toml
    [dependencies]
    codex-common = { path = "../common", features = ["cli"] }
    dotenvy = "0.15.7"
    
  • Fail Softly: Ignore missing files and parse errors; never panic on dotenv load.
    dotenvy::from_path(some_path).ok(); // ignore errors intentionally
    dotenvy::dotenv().ok();
    
  • Keep Side Effects Minimal: Only modify the process environment—no logging or user-facing output when loading.
    // no println!/tracing during dotenv load
    

DONTs

  • Dont Load Late: Avoid calling load_dotenv() after starting the runtime or in spawned tasks.
    // ❌ Bad: too late; threads already exist
    let rt = tokio::runtime::Runtime::new()?;
    rt.block_on(async {
        codex_common::dotenv::load_dotenv(); // too late
    });
    
  • Dont Unwrap on IO: Never unwrap()/expect() dotenv results; keep startup resilient.
    // ❌ Bad
    dotenvy::dotenv().expect("must have .env");
    // ✅ Good
    dotenvy::dotenv().ok();
    
  • Dont Reimplement Home Discovery: Dont hardcode ~/.codex; rely on find_codex_home().
    // ❌ Bad
    let path = dirs::home_dir().unwrap().join(".codex/.env");
    // ✅ Good
    let path = codex_core::config::find_codex_home()?.join(".env");
    
  • Dont Leak Secrets: Dont print or log env values loaded from .env.
    // ❌ Bad
    println!("{}", std::env::var("OPENAI_API_KEY").unwrap());
    
  • Dont Make It Global by Default: Dont include dotenv in non-CLI builds; keep it behind the cli feature.
    # ❌ Bad: unconditional dependency
    codex-common = { path = "../common" }
    # ✅ Good
    codex-common = { path = "../common", features = ["cli"] }
    
  • Dont Treat Missing CODEX_HOME as Error: If CODEX_HOME isnt set or the file isnt present, proceed without failing.
    if let Ok(home) = codex_core::config::find_codex_home() {
        dotenvy::from_path(home.join(".env")).ok();
    } // else: do nothing