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