Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 12 additions & 2 deletions src/claude/claudeLocal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { mkdirSync, existsSync } from "node:fs";
import { randomUUID } from "node:crypto";
import { logger } from "@/ui/logger";
import { claudeCheckSession } from "./utils/claudeCheckSession";
import { claudeFindLastSession } from "./utils/claudeFindLastSession";
import { getProjectPath } from "./utils/path";
import { projectPath } from "@/projectPath";
import { systemPrompt } from "./utils/systemPrompt";
Expand Down Expand Up @@ -33,10 +34,19 @@ export async function claudeLocal(opts: {
// - If resuming an existing session: use --resume (Claude keeps the same session ID)
// - If starting fresh: generate UUID and pass via --session-id
let startFrom = opts.sessionId;
if (opts.sessionId && !claudeCheckSession(opts.sessionId, opts.path)) {
startFrom = null;

// Convert --continue to --resume: find last session and use existing resume logic
if (!startFrom && opts.claudeArgs?.includes('--continue')) {
const lastSession = claudeFindLastSession(opts.path);
if (lastSession) {
startFrom = lastSession;
logger.debug(`[ClaudeLocal] Converting --continue to --resume ${lastSession}`);
}
// Remove --continue from claudeArgs since we're handling it
opts.claudeArgs = opts.claudeArgs?.filter(arg => arg !== '--continue');
}


// Generate new session ID if not resuming
const newSessionId = startFrom ? null : randomUUID();
const effectiveSessionId = startFrom || newSessionId!;
Expand Down
35 changes: 35 additions & 0 deletions src/claude/utils/claudeFindLastSession.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { readdirSync, statSync, readFileSync } from 'node:fs';
import { join } from 'node:path';
import { getProjectPath } from './path';
import { claudeCheckSession } from './claudeCheckSession';

/**
* Finds the most recently modified VALID session in the project directory.
* A valid session must contain at least one message with a uuid field.
* Returns the session ID (filename without .jsonl extension) or null if no valid sessions found.
*/
export function claudeFindLastSession(workingDirectory: string): string | null {
try {
const projectDir = getProjectPath(workingDirectory);
const files = readdirSync(projectDir)
.filter(f => f.endsWith('.jsonl'))
.map(f => {
const sessionId = f.replace('.jsonl', '');
// Check if this is a valid session
if (claudeCheckSession(sessionId, workingDirectory)) {
return {
name: f,
sessionId: sessionId,
mtime: statSync(join(projectDir, f)).mtime.getTime()
};
}
return null;
})
.filter(f => f !== null)
.sort((a, b) => b.mtime - a.mtime); // Most recent valid session first

return files.length > 0 ? files[0].sessionId : null;
} catch {
return null;
}
}