Skip to content

Support non-ASCII project paths (Claude session listing + Codex header crash)#207

Open
bbsngg wants to merge 2 commits into
mainfrom
fix/claude-session-dir-resolution
Open

Support non-ASCII project paths (Claude session listing + Codex header crash)#207
bbsngg wants to merge 2 commits into
mainfrom
fix/claude-session-dir-resolution

Conversation

@bbsngg

@bbsngg bbsngg commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

Two independent fixes for projects whose filesystem path contains non-ASCII characters (e.g. a Chinese path like /Users/you/Documents/项目/demo).


Fix 1 — Claude sessions could not be opened

Problem: /session/<id> rendered blank. dr-claw located Claude session jsonl by joining ~/.claude/projects/<encodeProjectPath(path)>, but the Claude CLI names those directories with a different, lossy scheme (every non-alphanumeric char → -). For non-ASCII paths the two never matched → getSessions() hit ENOENT → empty list.

Approach: Rather than replicate the CLI's undocumented encoding (would break on any CLI change and need a config/DB migration), discover the directories by the cwd recorded inside their jsonl files — a data fact independent of any naming convention.

New resolveClaudeProjectDirs() builds a reverse index (real path → directory names), used by every consumer that previously joined the dir by name: getSessions / getSessionMessages / deleteSession / renameSession / deleteTrashedProject / reconcileClaudeSessionIndex (server/projects.js), getClaudeProjectDirs (server/project-token-usage.js), and the session token-usage route (server/index.js, which also drops a buggy inline encoder missing .). encodeProjectPath, the config file, the DB and the frontend are unchanged; no migration.


Fix 2 — Codex crashed: x-codex-turn-metadata header

Problem: Starting a Codex turn failed with UTF-8 encoding error: failed to convert header to a str for header name 'x-codex-turn-metadata'Reconnecting... 5/5. codex-cli embeds the workspace path verbatim into an HTTP header, and HTTP header values must be ASCII/ISO-8859-1. (codex-cli 0.139.0 is the latest, so no version bump fixes it.)

Approach: Verified that codex-cli keeps the -C/--cd value verbatim and does not canonicalize symlinks (its rendered <cwd>/<workspace_roots> keep the symlink path). So we run Codex inside an ASCII-only symlink under ~/.dr-claw/codex-cwd/<slug>-<hash> → real project dir. The header stays ASCII; file ops still resolve to the real directory.

  • New resolveCodexWorkingDirectory() (server/utils/codexWorkingDir.js): ASCII paths pass through unchanged (zero behaviour change); non-ASCII paths get a stable, idempotent ASCII symlink; any failure falls back to the real path.
  • queryCodex hands the SDK the shadow path but keeps the real path for session indexing and stage tags.
  • normalizeComparablePath now resolves symlinks (best-effort realpath) so Codex sessions recorded under the shadow cwd still associate to the real project.

Trade-off: for non-ASCII projects, Codex's environment_context and tool output show the shadow path instead of the real path. The slug keeps it recognizable; dr-claw's own project association is unaffected.


Note on Gemini

The Gemini CLI does not have this class of bug: it sends workspace/cwd context in the request JSON body (UTF-8), not in any HTTP header, so non-ASCII paths are fine. No change needed.


Tests

server/__tests__/claude-dir-resolve.test.mjs and server/__tests__/codex-nonascii-path.test.mjs cover both fixes (non-ASCII resolution, ASCII no-regression, multi-dir merge, cache invalidation, reconcile retry; Codex ASCII passthrough, symlink mapping, idempotence, end-to-end session association). Full suite: 104 passing.

🤖 Generated with Claude Code

@bbsngg bbsngg changed the title Resolve Claude session dirs by recorded cwd, not CLI encoding Support non-ASCII project paths (Claude session listing + Codex header crash) Jun 10, 2026
@bbsngg bbsngg force-pushed the fix/claude-session-dir-resolution branch from 8fb8f78 to 460704b Compare June 10, 2026 03:56
Two independent fixes for projects whose filesystem path contains non-ASCII
characters (e.g. a Chinese path).

Fix 1 — Claude sessions could not be opened. dr-claw located session jsonl by
joining ~/.claude/projects/<encodeProjectPath(path)>, but the Claude CLI names
those directories with a different, lossy scheme (every non-alphanumeric char
-> '-'). For non-ASCII paths the two never matched, so getSessions() hit ENOENT
and /session/<id> rendered blank. Rather than replicate the CLI's undocumented
encoding (which would break on any CLI change and need a config/DB migration),
discover the directories by the cwd recorded inside their jsonl files. New
resolveClaudeProjectDirs() builds a reverse index (real path -> dir names) and
is used by every consumer that previously joined the directory by name:
getSessions / getSessionMessages / deleteSession / renameSession /
deleteTrashedProject / reconcileClaudeSessionIndex (server/projects.js),
getClaudeProjectDirs (server/project-token-usage.js), and the session
token-usage route (server/index.js, which also drops a buggy inline encoder
missing '.'). reconcileClaudeSessionIndex retries with a fresh index when the
CLI just created a new directory; the index is invalidated together with the
existing projectDirectoryCache. encodeProjectPath, the config file, the
database and the frontend are unchanged; no migration.

Fix 2 — Codex crashed with "failed to convert header to a str for header name
'x-codex-turn-metadata'". codex-cli embeds the workspace path verbatim into an
HTTP header, and header values must be ASCII/ISO-8859-1 (codex-cli 0.139.0 is
latest, so no version bump fixes it). codex-cli keeps the -C/--cd value
verbatim and does not canonicalize symlinks, so we run Codex inside an
ASCII-only symlink under ~/.dr-claw/codex-cwd/<slug>-<hash> that points at the
real project dir. New resolveCodexWorkingDirectory() (server/utils/codexWorkingDir.js):
ASCII paths pass through unchanged (zero behaviour change); non-ASCII paths get
a stable, idempotent ASCII symlink; any failure falls back to the real path.
queryCodex hands the SDK the shadow path but keeps the real path for session
indexing and stage tags. normalizeComparablePath now resolves symlinks
(best-effort realpath) so Codex sessions recorded under the shadow cwd still
associate to the real project in getCodexSessions.

Tests: server/__tests__/claude-dir-resolve.test.mjs and
server/__tests__/codex-nonascii-path.test.mjs cover non-ASCII resolution, ASCII
no-regression, multi-dir merge, cache invalidation, reconcile retry, Codex
ASCII passthrough, symlink mapping, idempotence, and end-to-end session
association. Full suite: 104 passing.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@bbsngg bbsngg force-pushed the fix/claude-session-dir-resolution branch from 460704b to ff87595 Compare June 10, 2026 03:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant