Skip to main content

codex_helper_core/
client_config.rs

1use 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_sqlite_dir() -> PathBuf {
26    codex_home().join("sqlite")
27}
28
29pub fn codex_app_db_path() -> PathBuf {
30    codex_sqlite_dir().join("codex-dev.db")
31}
32
33pub fn codex_switch_state_path() -> PathBuf {
34    codex_home().join("codex-helper-switch-state.json")
35}
36
37pub fn codex_auth_path() -> PathBuf {
38    codex_home().join("auth.json")
39}
40
41pub fn codex_models_cache_path() -> PathBuf {
42    codex_home().join("models_cache.json")
43}
44
45pub fn claude_home() -> PathBuf {
46    resolve_home_dir("CLAUDE_HOME", ".claude")
47}
48
49pub fn claude_settings_path() -> PathBuf {
50    let dir = claude_home();
51    let settings = dir.join("settings.json");
52    if settings.exists() {
53        return settings;
54    }
55    let legacy = dir.join("claude.json");
56    if legacy.exists() {
57        return legacy;
58    }
59    settings
60}
61
62pub fn claude_settings_backup_path_for(path: &Path) -> PathBuf {
63    let mut backup = path.to_path_buf();
64    let file_name = backup
65        .file_name()
66        .map(|name| name.to_string_lossy().to_string())
67        .unwrap_or_else(|| "settings.json".to_string());
68    backup.set_file_name(format!("{file_name}.codex-helper-backup"));
69    backup
70}
71
72pub fn claude_settings_backup_path() -> PathBuf {
73    claude_settings_backup_path_for(&claude_settings_path())
74}
75
76pub fn is_claude_absent_backup_sentinel(text: &str) -> bool {
77    text.trim() == CLAUDE_ABSENT_BACKUP_SENTINEL
78}