From bbd5e82abd0196b6d341484d7726391c81c36c7f Mon Sep 17 00:00:00 2001 From: Oleg Samarin Date: Mon, 13 Apr 2026 23:10:38 +0300 Subject: [PATCH 1/2] Fixed "Open with Claude Code" context menu not applying Extra CLI args MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit autoStart(File, String) was passing null as extraCliArgs to the three-argument overload, so the profile's Extra CLI args setting (configured in Tools → Options → Profiles) was silently discarded when launching from the project context menu. Fix: resolve the profile via ClaudeProfileStore.findByName() and forward its extraCliArgs. The IDE-restore path (autoStart with three args) already passes savedExtraCliArgs correctly and is unaffected. Resolves: #23 Co-Authored-By: Claude Sonnet 4.6 --- CHANGELOG.md | 1 + pom.xml | 2 +- .../nbclaudecodegui/ui/ClaudeSessionTab.java | 8 ++- .../ui/ClaudeSessionTabAutoStartTest.java | 49 +++++++++++++++++++ 4 files changed, 58 insertions(+), 2 deletions(-) create mode 100644 src/test/java/io/github/nbclaudecodegui/ui/ClaudeSessionTabAutoStartTest.java diff --git a/CHANGELOG.md b/CHANGELOG.md index 2690be35..99fb7dcd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,4 @@ +- Fixed "Open with Claude Code" context menu not applying the global Extra CLI args setting (https://github.com/nbclaudecodegui/NetbeansClaudeCodeGui/issues/23) - Added alphabetical sorting to the "Select Project" dropdown (https://github.com/nbclaudecodegui/NetbeansClaudeCodeGui/issues/21) - Fixed Default profile settings (API key, connection type, proxy, etc.) not being saved when edited in Tools → Options → Claude Code → Profiles - Fixed MCP config not working on Windows due to quote stripping in CreateProcess (https://github.com/nbclaudecodegui/NetbeansClaudeCodeGui/issues/13) diff --git a/pom.xml b/pom.xml index 69c8dd62..a353aa74 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ io.github.nbclaudecodegui netbeans-claude-code-gui - 0.21.41-SNAPSHOT + 0.21.42-SNAPSHOT nbm Netbeans Claude Code GUI NetBeans plugin that provides a GUI for Claude Code CLI — run claude code sessions directly inside the IDE. diff --git a/src/main/java/io/github/nbclaudecodegui/ui/ClaudeSessionTab.java b/src/main/java/io/github/nbclaudecodegui/ui/ClaudeSessionTab.java index 93886df9..74104536 100644 --- a/src/main/java/io/github/nbclaudecodegui/ui/ClaudeSessionTab.java +++ b/src/main/java/io/github/nbclaudecodegui/ui/ClaudeSessionTab.java @@ -576,11 +576,17 @@ public boolean isSessionActive() { /** * Starts a session for {@code dir} with {@code profileName} without showing any dialogs. * + *

The profile's {@code extraCliArgs} are resolved here so that the global + * "Extra CLI args" setting in Tools → Options is honoured when a session is + * launched from the project context menu ("Open with Claude Code"). + * Previously passing {@code null} meant the setting was silently ignored. + * * @param dir working directory * @param profileName profile name, or {@code null} for Default */ public void autoStart(File dir, String profileName) { - autoStart(dir, profileName, null); + ClaudeProfile profile = ClaudeProfileStore.findByName(profileName); + autoStart(dir, profileName, profile.getExtraCliArgs()); } public void autoStart(File dir, String profileName, String extraCliArgs) { diff --git a/src/test/java/io/github/nbclaudecodegui/ui/ClaudeSessionTabAutoStartTest.java b/src/test/java/io/github/nbclaudecodegui/ui/ClaudeSessionTabAutoStartTest.java new file mode 100644 index 00000000..7d2dee0b --- /dev/null +++ b/src/test/java/io/github/nbclaudecodegui/ui/ClaudeSessionTabAutoStartTest.java @@ -0,0 +1,49 @@ +package io.github.nbclaudecodegui.ui; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.util.concurrent.atomic.AtomicReference; +import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.*; + +/** + * Regression tests for issue #23: {@link ClaudeSessionTab#autoStart(File, String)} + * must forward the profile's {@code extraCliArgs} to the underlying session start, + * not pass {@code null}. + * + *

Before the fix, {@code autoStart(File, String)} called + * {@code autoStart(dir, profileName, null)}, silently discarding any Extra CLI + * args configured for the profile in Tools → Options → Profiles. + */ +class ClaudeSessionTabAutoStartTest { + + /** + * Verifies that {@code autoStart(File, String)} passes a non-null + * {@code extraCliArgs} string to the three-argument overload. + * + *

A non-null value guarantees that the profile's CLI args setting + * (even if empty) is forwarded rather than dropped. + */ + @Test + void autoStart_twoArg_passesNonNullExtraCliArgs() throws IOException { + AtomicReference capturedExtra = new AtomicReference<>("UNSET"); + + ClaudeSessionTab tab = new ClaudeSessionTab() { + @Override + public void autoStart(File dir, String profileName, String extraCliArgs) { + capturedExtra.set(extraCliArgs); + } + }; + + File tmpDir = Files.createTempDirectory("autostart-test").toFile(); + try { + tab.autoStart(tmpDir, null); + assertNotNull(capturedExtra.get(), + "autoStart(File,String) must not pass null extraCliArgs to the " + + "three-argument overload — profile extraCliArgs would be silently discarded"); + } finally { + tmpDir.delete(); + } + } +} From 79aa9f31f61c1c013b3486c9d7dfb785fa507814 Mon Sep 17 00:00:00 2001 From: Oleg Samarin Date: Tue, 14 Apr 2026 09:12:38 +0300 Subject: [PATCH 2/2] Fixed findByName() returning createDefault() instead of preference-backed Default ClaudeProfile.createDefault() constructs a profile with all fields set to empty defaults without reading NbPreferences. As a result, findByName(null/blank) returned a bare Default profile, silently discarding the user's configured API key, proxy, extraCliArgs, and other settings. Fix: - Added ClaudeProfileStore.getDefaultProfile() that goes through getProfiles(), which applies stored settings from NbPreferences to the Default profile. - findByName() now delegates to getDefaultProfile() for null/blank names, and uses it as the fallback for unknown named profiles. - Removed unused resolveProfile() from ClaudeProjectProperties (dead code). Co-Authored-By: Claude Sonnet 4.6 --- CHANGELOG.md | 2 +- pom.xml | 2 +- .../settings/ClaudeProfileStore.java | 26 ++++++++--- .../settings/ClaudeProjectProperties.java | 30 ++----------- .../settings/ClaudeProfileStoreTest.java | 43 +++++++++++++++++++ .../settings/ClaudeProjectPropertiesTest.java | 10 ----- 6 files changed, 67 insertions(+), 46 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 99fb7dcd..388d1860 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ -- Fixed "Open with Claude Code" context menu not applying the global Extra CLI args setting (https://github.com/nbclaudecodegui/NetbeansClaudeCodeGui/issues/23) +- Fixed "Open with Claude Code" context menu not applying Default profile settings (API key, proxy, Extra CLI args, etc.) (https://github.com/nbclaudecodegui/NetbeansClaudeCodeGui/issues/23) - Added alphabetical sorting to the "Select Project" dropdown (https://github.com/nbclaudecodegui/NetbeansClaudeCodeGui/issues/21) - Fixed Default profile settings (API key, connection type, proxy, etc.) not being saved when edited in Tools → Options → Claude Code → Profiles - Fixed MCP config not working on Windows due to quote stripping in CreateProcess (https://github.com/nbclaudecodegui/NetbeansClaudeCodeGui/issues/13) diff --git a/pom.xml b/pom.xml index a353aa74..0ff515e4 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ io.github.nbclaudecodegui netbeans-claude-code-gui - 0.21.42-SNAPSHOT + 0.21.45-SNAPSHOT nbm Netbeans Claude Code GUI NetBeans plugin that provides a GUI for Claude Code CLI — run claude code sessions directly inside the IDE. diff --git a/src/main/java/io/github/nbclaudecodegui/settings/ClaudeProfileStore.java b/src/main/java/io/github/nbclaudecodegui/settings/ClaudeProfileStore.java index ccfa8a60..1d739cd0 100644 --- a/src/main/java/io/github/nbclaudecodegui/settings/ClaudeProfileStore.java +++ b/src/main/java/io/github/nbclaudecodegui/settings/ClaudeProfileStore.java @@ -100,6 +100,22 @@ public static List getProfiles() { return result; } + /** + * Returns the preference-backed Default profile. + * + *

Unlike {@link ClaudeProfile#createDefault()}, this method goes through + * {@link #getProfiles()}, which loads stored settings (API key, proxy, + * extraCliArgs, etc.) from {@code NbPreferences}. Callers that need the + * Default profile should use this method so the user's configuration is + * honoured rather than silently discarded. + * + * @return the Default profile with settings loaded from preferences + */ + public static ClaudeProfile getDefaultProfile() { + return getProfiles().stream().filter(ClaudeProfile::isDefault).findFirst() + .orElseGet(ClaudeProfile::createDefault); + } + /** * Looks up a profile by name. * @@ -108,14 +124,10 @@ public static List getProfiles() { */ public static ClaudeProfile findByName(String name) { if (name == null || name.isBlank()) { - return ClaudeProfile.createDefault(); - } - for (ClaudeProfile p : getProfiles()) { - if (p.getName().equals(name)) { - return p; - } + return getDefaultProfile(); } - return ClaudeProfile.createDefault(); + return getProfiles().stream().filter(p -> p.getName().equals(name)).findFirst() + .orElseGet(ClaudeProfileStore::getDefaultProfile); } // ------------------------------------------------------------------------- diff --git a/src/main/java/io/github/nbclaudecodegui/settings/ClaudeProjectProperties.java b/src/main/java/io/github/nbclaudecodegui/settings/ClaudeProjectProperties.java index 3538388b..509a8f43 100644 --- a/src/main/java/io/github/nbclaudecodegui/settings/ClaudeProjectProperties.java +++ b/src/main/java/io/github/nbclaudecodegui/settings/ClaudeProjectProperties.java @@ -20,8 +20,9 @@ * // Assign a profile to a project * ClaudeProjectProperties.setProfileName(projectDir, "MyProfile"); * - * // Retrieve the assigned profile (falls back to Default) - * ClaudeProfile profile = ClaudeProjectProperties.resolveProfile(projectDir); + * // Retrieve the assigned profile name (falls back to Default when blank) + * String profileName = ClaudeProjectProperties.getProfileName(projectDir); + * ClaudeProfile profile = ClaudeProfileStore.findByName(profileName); * } */ public final class ClaudeProjectProperties { @@ -51,31 +52,6 @@ public static String getProfileName(File projectDir) { .get(KEY_PREFIX + projectDir.getAbsolutePath(), ""); } - /** - * Resolves the {@link ClaudeProfile} for the given project directory. - * - *

If no profile name is stored, or the stored name is blank, the - * Default profile is returned. If the stored name cannot be found in - * {@link ClaudeProfileStore}, the Default profile is returned and a - * warning is logged. - * - * @param projectDir the project root directory; may be {@code null} - * @return the assigned profile, or the Default profile if not set / not found - */ - public static ClaudeProfile resolveProfile(File projectDir) { - String name = getProfileName(projectDir); - if (name.isBlank()) { - return ClaudeProfile.createDefault(); - } - ClaudeProfile found = ClaudeProfileStore.findByName(name); - if (found.isDefault() && !name.isBlank()) { - LOG.warning("Profile '" + name + "' assigned to project " - + (projectDir != null ? projectDir.getAbsolutePath() : "null") - + " not found — using Default."); - } - return found; - } - // ------------------------------------------------------------------------- // Write // ------------------------------------------------------------------------- diff --git a/src/test/java/io/github/nbclaudecodegui/settings/ClaudeProfileStoreTest.java b/src/test/java/io/github/nbclaudecodegui/settings/ClaudeProfileStoreTest.java index 063060b5..ed834daf 100644 --- a/src/test/java/io/github/nbclaudecodegui/settings/ClaudeProfileStoreTest.java +++ b/src/test/java/io/github/nbclaudecodegui/settings/ClaudeProfileStoreTest.java @@ -83,6 +83,49 @@ void findByName_nullName_returnsDefault() { assertTrue(found.isDefault()); } + @Test + void findByName_unknownName_returnsDefault() { + ClaudeProfile found = ClaudeProfileStore.findByName("nonexistent-profile-xyz"); + assertTrue(found.isDefault(), + "findByName with unknown name must fall back to the Default profile"); + } + + // ------------------------------------------------------------------------- + // getDefaultProfile (issue #23) + // ------------------------------------------------------------------------- + + /** + * Regression test for issue #23: {@code getDefaultProfile()} must return + * the preference-backed Default profile, matching what {@code getProfiles()} + * returns — not a bare {@code createDefault()} with empty fields. + * + *

{@code createDefault()} sets {@code extraCliArgs = ""} unconditionally, + * so using it in {@code findByName(null)} would silently discard any Extra + * CLI args the user configured in Tools → Options. + */ + @Test + void getDefaultProfile_isDefault() { + ClaudeProfile p = ClaudeProfileStore.getDefaultProfile(); + assertTrue(p.isDefault(), "getDefaultProfile() must return the Default profile"); + assertEquals("Default", p.getName()); + } + + @Test + void getDefaultProfile_matchesGetProfiles() { + ClaudeProfile fromList = ClaudeProfileStore.getProfiles().get(0); + ClaudeProfile fromMethod = ClaudeProfileStore.getDefaultProfile(); + assertEquals(fromList.getExtraCliArgs(), fromMethod.getExtraCliArgs(), + "getDefaultProfile() must return the same extraCliArgs as getProfiles().get(0)"); + } + + @Test + void findByName_null_delegatesToGetDefaultProfile() { + ClaudeProfile fromFind = ClaudeProfileStore.findByName(null); + ClaudeProfile fromMethod = ClaudeProfileStore.getDefaultProfile(); + assertEquals(fromMethod.getExtraCliArgs(), fromFind.getExtraCliArgs(), + "findByName(null) must delegate to getDefaultProfile()"); + } + // ------------------------------------------------------------------------- // saveProfile / Default cannot be saved // ------------------------------------------------------------------------- diff --git a/src/test/java/io/github/nbclaudecodegui/settings/ClaudeProjectPropertiesTest.java b/src/test/java/io/github/nbclaudecodegui/settings/ClaudeProjectPropertiesTest.java index fe0debaf..75ee9897 100644 --- a/src/test/java/io/github/nbclaudecodegui/settings/ClaudeProjectPropertiesTest.java +++ b/src/test/java/io/github/nbclaudecodegui/settings/ClaudeProjectPropertiesTest.java @@ -72,16 +72,6 @@ void setProfileName_nullName_clearsEntry() { } catch (Exception ignored) {} } - // ------------------------------------------------------------------------- - // resolveProfile — null dir falls back to Default - // ------------------------------------------------------------------------- - - @Test - void resolveProfile_nullDir_returnsDefault() { - ClaudeProfile profile = ClaudeProjectProperties.resolveProfile(null); - assertTrue(profile.isDefault()); - } - // ------------------------------------------------------------------------- // renameAssignments // -------------------------------------------------------------------------