Skip to content

feat(sidebar): include the session directory in the copied resume command#221

Open
1fanwang wants to merge 1 commit into
matt1398:mainfrom
1fanwang:resume-command-include-cwd
Open

feat(sidebar): include the session directory in the copied resume command#221
1fanwang wants to merge 1 commit into
matt1398:mainfrom
1fanwang:resume-command-include-cwd

Conversation

@1fanwang

@1fanwang 1fanwang commented Jun 30, 2026

Copy link
Copy Markdown

Why

The sidebar's "Copy Resume Command" copies claude --resume <id>. That resumes
in whatever directory the terminal happens to be in, so you have to manually
cd into the project first — the friction #34 set out to remove.

What

Prefixes the copied command with cd "<cwd>", using the project's resolved path
(the encoded project directory is the session's launch cwd). The directory is
double-quoted so paths with spaces survive the paste. Falls back to the bare
claude --resume <id> when the path can't be resolved.

The command string is built by a small pure helper (buildResumeCommand), so
the behaviour is unit-tested directly.

Validation

pnpm typecheck, pnpm lint, pnpm test, and pnpm build are clean. Four new
unit tests cover the bare command, the cwd prefix, space-quoting, and the
empty-path fallback.

Note: this touches SessionContextMenu.tsx, which #215 also edits. The change
is additive (only the resume string plus a store lookup), so it should rebase
cleanly whichever lands first.

Refs #34.

Summary by CodeRabbit

  • New Features
    • Improved the “Copy Resume Command” action so it includes the correct project folder when available.
    • Resume commands now open in the matching workspace directory, helping sessions continue in the right context.
  • Bug Fixes
    • Paths with spaces are now handled correctly when copying a resume command.
    • Empty or missing project paths fall back to the simpler resume command.

…mand

"Copy Resume Command" copied `claude --resume <id>`, which resumes in whatever directory the terminal happens to be in — so users had to manually cd into the project first. Prefix the command with `cd "<cwd>"` using the project's resolved path (the encoded project dir is the session's launch cwd), quoted so paths with spaces survive the paste. Falls back to the bare command when the path can't be resolved.

The command builder is extracted as a pure, unit-tested helper (buildResumeCommand).
@coderabbitai coderabbitai Bot added the feature request New feature or request label Jun 30, 2026

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a helper function buildResumeCommand to automatically change directories to the session's working directory before resuming a Claude Code session, updating the context menu to use this command. The feedback suggests normalizing Windows backslashes to forward slashes to prevent shell syntax errors on cross-platform environments, along with adding a corresponding unit test.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment on lines +10 to +16
export function buildResumeCommand(sessionId: string, cwd?: string): string {
const resume = `claude --resume ${sessionId}`;
if (!cwd) {
return resume;
}
return `cd "${cwd}" && ${resume}`;
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

When generating shell commands with paths on Windows, backslashes (\) can cause issues when pasted into POSIX-like shells (such as Git Bash, WSL, or macOS/Linux terminals if accessing a cross-mounted drive). Specifically, a trailing backslash (e.g., C:\path\to\project\) will escape the closing double quote (\"), leading to an unclosed quote syntax error in bash/zsh.

Since Windows CMD, PowerShell, and POSIX shells all support forward slashes (/) for directory navigation, we can normalize the path by replacing all backslashes with forward slashes. This ensures the command is robust and cross-platform.

Suggested change
export function buildResumeCommand(sessionId: string, cwd?: string): string {
const resume = `claude --resume ${sessionId}`;
if (!cwd) {
return resume;
}
return `cd "${cwd}" && ${resume}`;
}
export function buildResumeCommand(sessionId: string, cwd?: string): string {
const resume = `claude --resume ${sessionId}`;
if (!cwd) {
return resume;
}
const normalizedCwd = cwd.replace(/\\/g, '/');
return `cd "${normalizedCwd}" && ${resume}`;
}

Comment on lines +21 to +24

it('falls back to the bare command for an empty working directory', () => {
expect(buildResumeCommand('abc-123', '')).toBe('claude --resume abc-123');
});

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Add a unit test to verify that Windows backslashes are correctly normalized to forward slashes in the generated command.

  it('normalizes Windows backslashes to forward slashes', () => {
    expect(buildResumeCommand('abc-123', 'C:\\Users\\me\\project')).toBe(
      'cd "C:/Users/me/project" && claude --resume abc-123'
    );
  });

  it('falls back to the bare command for an empty working directory', () => {
    expect(buildResumeCommand('abc-123', '')).toBe('claude --resume abc-123');
  });

@coderabbitai

coderabbitai Bot commented Jun 30, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Adds a buildResumeCommand(sessionId, cwd?) utility that constructs a claude --resume shell command, optionally prefixed with cd "<cwd>" &&. SessionContextMenu now resolves the session's project path from the store and passes it to this utility when copying the resume command.

Changes

Resume Command with Project Path

Layer / File(s) Summary
buildResumeCommand utility and tests
src/renderer/utils/resumeCommand.ts, test/renderer/utils/resumeCommand.test.ts
New exported function returns claude --resume <sessionId> bare, or prefixed with cd "<cwd>" && when a working directory is provided; tests cover bare, cwd, spaced paths, and empty-string fallback.
SessionContextMenu wiring
src/renderer/components/sidebar/SessionContextMenu.tsx
Imports buildResumeCommand, adds projectId to props destructuring, derives projectPath from the renderer store by matching projectId, and passes it to buildResumeCommand in the "Copy Resume Command" action.

Suggested labels

feature request

🚥 Pre-merge checks | ✅ 2
✅ Passed checks (2 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

ESLint install failed: private package registry requires authentication. Disable ESLint in CodeRabbit settings or use public packages.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
test/renderer/utils/resumeCommand.test.ts (1)

3-3: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Use the @renderer alias for this import.

Reaching into src via ../../../ makes the test brittle and sidesteps the repo's import convention. @renderer/utils/resumeCommand keeps this as a direct file import without coupling the test to directory depth.

Suggested change
-import { buildResumeCommand } from '../../../src/renderer/utils/resumeCommand';
+import { buildResumeCommand } from '`@renderer/utils/resumeCommand`';

As per coding guidelines, "Use path aliases for imports" and "Renderer utils, hooks, and types should NOT use barrel exports - import directly from specific files."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@test/renderer/utils/resumeCommand.test.ts` at line 3, The test import is
using a brittle relative path instead of the repo’s renderer alias. Update the
import in resumeCommand.test.ts to use `@renderer/utils/resumeCommand` directly,
matching the import convention for renderer utils and avoiding coupling the test
to directory depth.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/renderer/utils/resumeCommand.ts`:
- Around line 10-15: The buildResumeCommand helper is inserting both cwd and
sessionId directly into a shell command, which can break on special characters
and allow shell expansion; update buildResumeCommand to use POSIX-safe single
quoting for both arguments before assembling the resume command. Keep the
existing command structure, but ensure the quoted cwd is used in the cd step and
the quoted sessionId is passed to claude --resume.

---

Nitpick comments:
In `@test/renderer/utils/resumeCommand.test.ts`:
- Line 3: The test import is using a brittle relative path instead of the repo’s
renderer alias. Update the import in resumeCommand.test.ts to use
`@renderer/utils/resumeCommand` directly, matching the import convention for
renderer utils and avoiding coupling the test to directory depth.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 7c366c4f-1b22-4afa-bcb4-759aaf8efd79

📥 Commits

Reviewing files that changed from the base of the PR and between 16cc3c8 and ba707a8.

📒 Files selected for processing (3)
  • src/renderer/components/sidebar/SessionContextMenu.tsx
  • src/renderer/utils/resumeCommand.ts
  • test/renderer/utils/resumeCommand.test.ts

Comment on lines +10 to +15
export function buildResumeCommand(sessionId: string, cwd?: string): string {
const resume = `claude --resume ${sessionId}`;
if (!cwd) {
return resume;
}
return `cd "${cwd}" && ${resume}`;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '--- file ---\n'
cat -n src/renderer/utils/resumeCommand.ts

printf '\n--- usages ---\n'
rg -n "buildResumeCommand|resumeCommand" src -S

printf '\n--- nearby related helpers ---\n'
rg -n "quote.*Arg|shell|escape.*arg|escape.*shell|cd \"" src/renderer src/main src/shared -S

Repository: matt1398/claude-devtools

Length of output: 253


🏁 Script executed:

#!/bin/bash
set -euo pipefail

python3 - <<'PY'
from pathlib import Path
p = Path('src/renderer/utils/resumeCommand.ts')
print(p.read_text())
PY

Repository: matt1398/claude-devtools

Length of output: 802


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '--- usages of buildResumeCommand ---'
rg -n "buildResumeCommand" src -S

echo
echo '--- nearby source for resumeCommand ---'
sed -n '1,120p' src/renderer/utils/resumeCommand.ts

echo
echo '--- sessionId/cwd data sources ---'
rg -n "\bsessionId\b|\bcwd\b" src/renderer src/shared src/main -S | sed -n '1,220p'

Repository: matt1398/claude-devtools

Length of output: 24239


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '--- SessionContextMenu ---'
sed -n '1,220p' src/renderer/components/sidebar/SessionContextMenu.tsx

echo
echo '--- projectPath / cwd provenance ---'
rg -n "projectPath" src/renderer/components/sidebar/SessionContextMenu.tsx src/renderer src/main -S

echo
echo '--- session id definition / shape ---'
rg -n "type .*Session|interface .*Session|id: string;|sessionId: string" src/main/types src/shared/types src/renderer/types -S | sed -n '1,220p'

Repository: matt1398/claude-devtools

Length of output: 27534


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '--- session id parsing/generation ---'
rg -n "sessionId.*(uuid|random|generate|basename|jsonl|id =|id:)|path.basename\\(.*sessionId|extract.*sessionId|session file" src/main src/renderer src/shared -S | sed -n '1,220p'

echo
echo '--- session-related type definitions ---'
sed -n '1,220p' src/main/types/domain.ts

Repository: matt1398/claude-devtools

Length of output: 14395


Quote both shell arguments in buildResumeCommand.

cwd is inserted into cd "..." && ..., which still allows shell expansion and breaks on embedded quotes/newlines. sessionId is unquoted too. Use POSIX-safe single quoting before copying the command.

Possible fix for POSIX shells
+function quotePosixArg(value: string): string {
+  return `'${value.replace(/'/g, "'\\''")}'`;
+}
+
 export function buildResumeCommand(sessionId: string, cwd?: string): string {
-  const resume = `claude --resume ${sessionId}`;
+  const resume = `claude --resume ${quotePosixArg(sessionId)}`;
   if (!cwd) {
     return resume;
   }
-  return `cd "${cwd}" && ${resume}`;
+  return `cd ${quotePosixArg(cwd)} && ${resume}`;
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
export function buildResumeCommand(sessionId: string, cwd?: string): string {
const resume = `claude --resume ${sessionId}`;
if (!cwd) {
return resume;
}
return `cd "${cwd}" && ${resume}`;
function quotePosixArg(value: string): string {
return `'${value.replace(/'/g, "'\\''")}'`;
}
export function buildResumeCommand(sessionId: string, cwd?: string): string {
const resume = `claude --resume ${quotePosixArg(sessionId)}`;
if (!cwd) {
return resume;
}
return `cd ${quotePosixArg(cwd)} && ${resume}`;
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/renderer/utils/resumeCommand.ts` around lines 10 - 15, The
buildResumeCommand helper is inserting both cwd and sessionId directly into a
shell command, which can break on special characters and allow shell expansion;
update buildResumeCommand to use POSIX-safe single quoting for both arguments
before assembling the resume command. Keep the existing command structure, but
ensure the quoted cwd is used in the cd step and the quoted sessionId is passed
to claude --resume.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feature request New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant