diff --git a/CHANGELOG.md b/CHANGELOG.md index df48bbc7..323dcf69 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,4 @@ +- Fixed process start errors and hang timeouts now logged to the IDE log file at SEVERE level - Added hang detection: configurable timeout (default 60 s) kills the process and shows an error if no PTY output is received after launch; set to 0 to disable - Fixed authentication for profiles with the "Claude API" connection type: the API key is now correctly recognised by Claude Code on session start - Added capability of changing the profile storage directory and sharing a single directory with several profiles diff --git a/pom.xml b/pom.xml index 35a46541..574403db 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ io.github.nbclaudecodegui netbeans-claude-code-gui - 0.21.29-SNAPSHOT + 0.21.34-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/controller/ClaudeSessionController.java b/src/main/java/io/github/nbclaudecodegui/controller/ClaudeSessionController.java index 4c4eb232..dfe80c14 100644 --- a/src/main/java/io/github/nbclaudecodegui/controller/ClaudeSessionController.java +++ b/src/main/java/io/github/nbclaudecodegui/controller/ClaudeSessionController.java @@ -73,6 +73,7 @@ public final class ClaudeSessionController { private ClaudeProcess claudeProcess; private PtyTtyConnector connector; + private java.io.File workingDir; /** Polls screen state every 500 ms; owned here to allow proper teardown. */ private javax.swing.Timer statusTimer; @@ -200,6 +201,7 @@ public void startProcess(java.io.File dir, String profileName, String extraCliAr SessionMode mode, String resumeSessionId, JediTermWidget widget) throws IOException { String tag = "[" + dir.getName() + "] "; + workingDir = dir; claudeProcess = new ClaudeProcess(); ClaudeProfile profile = ClaudeProfileStore.findByName(profileName); customModelIds = profile != null ? new ArrayList<>(profile.getCustomModels()) : List.of(); @@ -979,7 +981,7 @@ public void setHangCallback(java.util.function.BiConsumer callba * @param timeoutSec the configured timeout that elapsed (for the error message) */ private void handleHang(int timeoutSec) { - LOG.warning("Hang detected: no PTY output received within " + timeoutSec + " s — killing process"); + LOG.severe("Hang detected in " + workingDir + ": no PTY output received within " + timeoutSec + " s — killing process"); String command = claudeProcess != null ? claudeProcess.getLastCommand() : ""; stopProcess(); java.util.function.BiConsumer cb = hangCallback; diff --git a/src/main/java/io/github/nbclaudecodegui/process/ClaudeProcess.java b/src/main/java/io/github/nbclaudecodegui/process/ClaudeProcess.java index d44b97a1..92c5f9c4 100644 --- a/src/main/java/io/github/nbclaudecodegui/process/ClaudeProcess.java +++ b/src/main/java/io/github/nbclaudecodegui/process/ClaudeProcess.java @@ -178,7 +178,7 @@ public PtyProcess start(String workingDir, ClaudeProfile profile, String extraCl appendSessionFlags(cmd, workingDir, env, extraCliArgs, mode, resumeSessionId); lastCommand = toShellCommand(cmd); - LOG.info("Claude command: " + lastCommand); + LOG.info("Claude command: " + lastCommand + " (dir: " + workingDir + ")"); PtyProcessBuilder builder = new PtyProcessBuilder(cmd.toArray(new String[0])) .setEnvironment(env) .setDirectory(workingDir) diff --git a/src/main/java/io/github/nbclaudecodegui/ui/ClaudeSessionTab.java b/src/main/java/io/github/nbclaudecodegui/ui/ClaudeSessionTab.java index 85164ad8..8938baa3 100644 --- a/src/main/java/io/github/nbclaudecodegui/ui/ClaudeSessionTab.java +++ b/src/main/java/io/github/nbclaudecodegui/ui/ClaudeSessionTab.java @@ -25,6 +25,7 @@ import java.io.ObjectInput; import java.io.ObjectOutput; import java.util.List; +import java.util.logging.Level; import java.util.logging.Logger; import javax.swing.BorderFactory; import javax.swing.Box; @@ -665,6 +666,7 @@ private void startSession(File dir, String profileName, String extraCliArgs, try { controller.startProcess(dir, profileName, extraCliArgs, mode, resumeSessionId, widget); } catch (IOException ex) { + LOG.log(Level.SEVERE, "Claude process failed to start in " + dir, ex); String command = controller.getLastAttemptedCommand(); String errorMsg = ex.getMessage() != null ? ex.getMessage() : ex.getClass().getSimpleName(); showStartError(command, errorMsg);