From 8efff30adda3c958d052bf2f386d16fad50f4511 Mon Sep 17 00:00:00 2001 From: Ben Vinegar Date: Mon, 13 Jul 2026 04:16:27 -0400 Subject: [PATCH] fix(config): resolve Windows user profile config --- .changeset/seven-pans-hunt.md | 5 +++++ src/core/config.test.ts | 23 +++++++++++++++++++++++ src/core/paths.test.ts | 11 +++++++++++ src/core/paths.ts | 5 +++-- 4 files changed, 42 insertions(+), 2 deletions(-) create mode 100644 .changeset/seven-pans-hunt.md diff --git a/.changeset/seven-pans-hunt.md b/.changeset/seven-pans-hunt.md new file mode 100644 index 00000000..23d8655f --- /dev/null +++ b/.changeset/seven-pans-hunt.md @@ -0,0 +1,5 @@ +--- +"hunkdiff": patch +--- + +Fix global config discovery on Windows when `HOME` is unavailable. diff --git a/src/core/config.test.ts b/src/core/config.test.ts index ac3a7f9f..94722838 100644 --- a/src/core/config.test.ts +++ b/src/core/config.test.ts @@ -263,6 +263,29 @@ describe("config resolution", () => { expect(overridden.input.options.transparentBackground).toBe(false); }); + test("loads global config from USERPROFILE when HOME is unavailable", () => { + const profile = createTempDir("hunk-config-profile-"); + mkdirSync(join(profile, ".config", "hunk"), { recursive: true }); + writeFileSync( + join(profile, ".config", "hunk", "config.toml"), + "transparent_background = true\n", + ); + + const configured = resolveConfiguredCliInput( + { + kind: "vcs", + staged: false, + options: {}, + }, + { + cwd: createTempDir("hunk-config-cwd-"), + env: { USERPROFILE: profile }, + }, + ); + + expect(configured.input.options.transparentBackground).toBe(true); + }); + test("defaults unspecified themes to github-dark-default, including piped pager-style patch input", () => { const home = createTempDir("hunk-config-home-"); const cwd = createTempDir("hunk-config-cwd-"); diff --git a/src/core/paths.test.ts b/src/core/paths.test.ts index 6badeed7..e81379e6 100644 --- a/src/core/paths.test.ts +++ b/src/core/paths.test.ts @@ -29,6 +29,17 @@ describe("paths", () => { expect(resolveHunkStatePath(env)).toBe(join("/tmp", "home", ".config", "hunk", "state.json")); }); + test("falls back to USERPROFILE when HOME is unavailable", () => { + const env = { USERPROFILE: join("/tmp", "windows-profile") } as NodeJS.ProcessEnv; + + expect(resolveGlobalConfigPath(env)).toBe( + join("/tmp", "windows-profile", ".config", "hunk", "config.toml"), + ); + expect(resolveHunkStatePath(env)).toBe( + join("/tmp", "windows-profile", ".config", "hunk", "state.json"), + ); + }); + test("locates the bundled Hunk review skill from source", () => { const resolvedPath = resolveBundledHunkReviewSkillPath([import.meta.dir]); diff --git a/src/core/paths.ts b/src/core/paths.ts index 7ee88bf8..4923e249 100644 --- a/src/core/paths.ts +++ b/src/core/paths.ts @@ -9,8 +9,9 @@ export function resolveUserConfigDir(env: NodeJS.ProcessEnv = process.env) { return env.XDG_CONFIG_HOME; } - if (env.HOME) { - return join(env.HOME, ".config"); + const home = env.HOME || env.USERPROFILE; + if (home) { + return join(home, ".config"); } return undefined;