Skip to content

Commit 9ba4155

Browse files
authored
feat(config): add cross-platform user-level config support (#20)
1 parent 5072717 commit 9ba4155

File tree

1 file changed

+54
-32
lines changed

1 file changed

+54
-32
lines changed

src/index.ts

Lines changed: 54 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,20 @@ import * as fs from "fs";
4343
import * as path from "path";
4444
import * as os from "os";
4545

46+
/**
47+
* Returns the user-level config directory based on the OS.
48+
* - Linux/macOS: XDG_CONFIG_HOME or ~/.config
49+
* - Windows: %APPDATA%
50+
*/
51+
function getUserConfigDir(): string {
52+
if (process.platform === "win32") {
53+
return process.env.APPDATA || path.join(os.homedir(), "AppData", "Roaming");
54+
}
55+
56+
// Linux, macOS, and other Unix-like systems: respect XDG_CONFIG_HOME
57+
return process.env.XDG_CONFIG_HOME || path.join(os.homedir(), ".config");
58+
}
59+
4660
function loadConfigFromPath(configPath: string): OhMyOpenCodeConfig | null {
4761
try {
4862
if (fs.existsSync(configPath)) {
@@ -64,53 +78,61 @@ function loadConfigFromPath(configPath: string): OhMyOpenCodeConfig | null {
6478
return null;
6579
}
6680

67-
function mergeConfigs(base: OhMyOpenCodeConfig, override: OhMyOpenCodeConfig): OhMyOpenCodeConfig {
81+
function mergeConfigs(
82+
base: OhMyOpenCodeConfig,
83+
override: OhMyOpenCodeConfig
84+
): OhMyOpenCodeConfig {
6885
return {
6986
...base,
7087
...override,
71-
agents: override.agents !== undefined
72-
? { ...(base.agents ?? {}), ...override.agents }
73-
: base.agents,
88+
agents:
89+
override.agents !== undefined
90+
? { ...(base.agents ?? {}), ...override.agents }
91+
: base.agents,
7492
disabled_agents: [
75-
...new Set([...(base.disabled_agents ?? []), ...(override.disabled_agents ?? [])])
93+
...new Set([
94+
...(base.disabled_agents ?? []),
95+
...(override.disabled_agents ?? []),
96+
]),
7697
],
7798
disabled_mcps: [
78-
...new Set([...(base.disabled_mcps ?? []), ...(override.disabled_mcps ?? [])])
99+
...new Set([
100+
...(base.disabled_mcps ?? []),
101+
...(override.disabled_mcps ?? []),
102+
]),
79103
],
80104
};
81105
}
82106

83107
function loadPluginConfig(directory: string): OhMyOpenCodeConfig {
84-
// User-level config paths
85-
const userConfigPaths = [
86-
path.join(os.homedir(), ".config", "opencode", "oh-my-opencode.json"),
87-
];
88-
89-
// Project-level config paths (higher precedence)
90-
const projectConfigPaths = [
91-
path.join(directory, ".opencode", "oh-my-opencode.json"),
92-
];
93-
94-
// Load user config first
95-
let config: OhMyOpenCodeConfig = {};
96-
for (const configPath of userConfigPaths) {
97-
const userConfig = loadConfigFromPath(configPath);
98-
if (userConfig) {
99-
config = userConfig;
100-
break;
101-
}
102-
}
108+
// User-level config path (OS-specific)
109+
const userConfigPath = path.join(
110+
getUserConfigDir(),
111+
"opencode",
112+
"oh-my-opencode.json"
113+
);
114+
115+
// Project-level config path
116+
const projectConfigPath = path.join(
117+
directory,
118+
".opencode",
119+
"oh-my-opencode.json"
120+
);
121+
122+
// Load user config first (base)
123+
let config: OhMyOpenCodeConfig = loadConfigFromPath(userConfigPath) ?? {};
103124

104125
// Override with project config
105-
for (const configPath of projectConfigPaths) {
106-
const projectConfig = loadConfigFromPath(configPath);
107-
if (projectConfig) {
108-
config = mergeConfigs(config, projectConfig);
109-
break;
110-
}
126+
const projectConfig = loadConfigFromPath(projectConfigPath);
127+
if (projectConfig) {
128+
config = mergeConfigs(config, projectConfig);
111129
}
112130

113-
log("Final merged config", { agents: config.agents, disabled_agents: config.disabled_agents, disabled_mcps: config.disabled_mcps });
131+
log("Final merged config", {
132+
agents: config.agents,
133+
disabled_agents: config.disabled_agents,
134+
disabled_mcps: config.disabled_mcps,
135+
});
114136
return config;
115137
}
116138

0 commit comments

Comments
 (0)