Skip to content
Open
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
33 changes: 33 additions & 0 deletions src/core/parser-claude.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -384,6 +384,39 @@ describe('parseClaudeSessions', () => {
}
});

// ---- workspace name resolution with underscores ----

it('resolves workspace name when path contains a folder with underscores', { timeout: 30_000 }, () => {
// Claude Code encodes underscores as hyphens, so the encoded name cannot be
// matched against readdirSync output unless underscores are normalized too.
const tmpBase = fs.mkdtempSync(path.join(longTmpDir(), 'claude-us-'));
const underscoreParent = path.join(tmpBase, 'my_home_dir');
const targetDir = path.join(underscoreParent, 'proj');
fs.mkdirSync(targetDir, { recursive: true });

const encodedDirName = targetDir
.replace(/^([a-zA-Z])(?=:)/, d => d.toLowerCase())
.replace(/[:\\/\s_]/g, '-');

const root = fs.mkdtempSync(path.join(longTmpDir(), 'claude-proj-'));
const projectsDir = path.join(root, 'projects');
const projDir = path.join(projectsDir, encodedDirName);
fs.mkdirSync(projDir, { recursive: true });
fs.writeFileSync(
path.join(projDir, 's.jsonl'),
[makeUser('hello'), makeAssistant('hi')].map(l => JSON.stringify(l)).join('\n'),
);

try {
const result = parseClaudeSessions(projectsDir);
expect(result).toHaveLength(1);
expect(result[0].workspaceName).toBe('proj');
} finally {
fs.rmSync(root, { recursive: true, force: true });
fs.rmSync(tmpBase, { recursive: true, force: true });
}
});

// ---- workspace name resolution with spaces ----

it('resolves workspace name when path contains a folder with spaces', { timeout: 30_000 }, () => {
Expand Down
4 changes: 2 additions & 2 deletions src/core/parser-claude.ts
Original file line number Diff line number Diff line change
Expand Up @@ -384,11 +384,11 @@ export function findClaudeDirs(): string[] {
}

/** Encode a single filesystem component the way Claude Code does:
* replace whitespace with hyphens. Path separators never appear in a single
* replace whitespace and underscores with hyphens. Path separators never appear in a single
* component name, and colons are not handled here because Windows component
* names cannot contain them. */
function encodeComponentForMatch(name: string): string {
return name.replace(/\s/g, '-');
return name.replace(/[\s_]/g, '-');
}

/**
Expand Down
Loading