Skip to main content

codex_cli/
paths.rs

1use std::env;
2use std::path::{Path, PathBuf};
3
4pub fn resolve_secret_dir() -> Option<PathBuf> {
5    if let Some(dir) = env_path("CODEX_SECRET_DIR") {
6        return Some(dir);
7    }
8
9    let feature_dir = resolve_feature_dir()?;
10    if feature_dir.join("init.zsh").is_file() || feature_dir.join("codex-tools.zsh").is_file() {
11        return Some(feature_dir.join("secrets"));
12    }
13    Some(feature_dir)
14}
15
16pub fn resolve_auth_file() -> Option<PathBuf> {
17    if let Some(path) = env_path("CODEX_AUTH_FILE") {
18        return Some(path);
19    }
20
21    let home = home_dir()?;
22    let primary = home.join(".codex").join("auth.json");
23    let fallback = home.join(".codex").join("auth.json");
24
25    let mut selected = primary.clone();
26    if selected == primary && !primary.exists() && fallback.exists() {
27        selected = fallback.clone();
28    } else if selected == fallback && !fallback.exists() && primary.exists() {
29        selected = primary.clone();
30    }
31    Some(selected)
32}
33
34pub fn resolve_secret_cache_dir() -> Option<PathBuf> {
35    if let Some(path) = env_path("CODEX_SECRET_CACHE_DIR") {
36        return Some(path);
37    }
38
39    let cache_root = if let Some(path) = env_path("ZSH_CACHE_DIR") {
40        path
41    } else {
42        resolve_zdotdir()?.join("cache")
43    };
44
45    Some(cache_root.join("codex").join("secrets"))
46}
47
48pub fn resolve_feature_dir() -> Option<PathBuf> {
49    let script_dir = resolve_script_dir()?;
50    let feature_dir = script_dir.join("_features").join("codex");
51    if feature_dir.is_dir() {
52        Some(feature_dir)
53    } else {
54        None
55    }
56}
57
58pub fn resolve_script_dir() -> Option<PathBuf> {
59    if let Some(path) = env_path("ZSH_SCRIPT_DIR") {
60        return Some(path);
61    }
62    Some(resolve_zdotdir()?.join("scripts"))
63}
64
65pub fn resolve_zdotdir() -> Option<PathBuf> {
66    if let Some(path) = env_path("ZDOTDIR") {
67        return Some(path);
68    }
69
70    if let Some(preload) = env_path("_ZSH_BOOTSTRAP_PRELOAD_PATH")
71        && let Some(parent) = parent_dir(&preload, 2)
72    {
73        return Some(parent);
74    }
75
76    let home = home_dir()?;
77    Some(home.join(".config").join("zsh"))
78}
79
80fn env_path(key: &str) -> Option<PathBuf> {
81    let raw = env::var_os(key)?;
82    if raw.is_empty() {
83        return None;
84    }
85    Some(PathBuf::from(raw))
86}
87
88fn home_dir() -> Option<PathBuf> {
89    env_path("HOME")
90}
91
92fn parent_dir(path: &Path, levels: usize) -> Option<PathBuf> {
93    let mut current = path;
94    for _ in 0..levels {
95        current = current.parent()?;
96    }
97    Some(current.to_path_buf())
98}