codex_helper_core/
client_config.rs1use std::env;
2use std::path::{Path, PathBuf};
3
4use dirs::home_dir;
5
6pub const CLAUDE_ABSENT_BACKUP_SENTINEL: &str = "{\"__codex_helper_backup_absent\":true}";
7
8fn resolve_home_dir(env_var: &str, default_dir_name: &str) -> PathBuf {
9 if let Ok(dir) = env::var(env_var) {
10 return PathBuf::from(dir);
11 }
12 home_dir()
13 .unwrap_or_else(|| PathBuf::from("."))
14 .join(default_dir_name)
15}
16
17pub fn codex_home() -> PathBuf {
18 resolve_home_dir("CODEX_HOME", ".codex")
19}
20
21pub fn codex_config_path() -> PathBuf {
22 codex_home().join("config.toml")
23}
24
25pub fn codex_switch_state_path() -> PathBuf {
26 codex_home().join("codex-helper-switch-state.json")
27}
28
29pub fn codex_auth_path() -> PathBuf {
30 codex_home().join("auth.json")
31}
32
33pub fn claude_home() -> PathBuf {
34 resolve_home_dir("CLAUDE_HOME", ".claude")
35}
36
37pub fn claude_settings_path() -> PathBuf {
38 let dir = claude_home();
39 let settings = dir.join("settings.json");
40 if settings.exists() {
41 return settings;
42 }
43 let legacy = dir.join("claude.json");
44 if legacy.exists() {
45 return legacy;
46 }
47 settings
48}
49
50pub fn claude_settings_backup_path_for(path: &Path) -> PathBuf {
51 let mut backup = path.to_path_buf();
52 let file_name = backup
53 .file_name()
54 .map(|name| name.to_string_lossy().to_string())
55 .unwrap_or_else(|| "settings.json".to_string());
56 backup.set_file_name(format!("{file_name}.codex-helper-backup"));
57 backup
58}
59
60pub fn claude_settings_backup_path() -> PathBuf {
61 claude_settings_backup_path_for(&claude_settings_path())
62}
63
64pub fn is_claude_absent_backup_sentinel(text: &str) -> bool {
65 text.trim() == CLAUDE_ABSENT_BACKUP_SENTINEL
66}