Point transcript lookup at the project directory Claude Code actually uses
Claude Code's project slug is not "slashes become dashes". Every
non-alphanumeric character becomes one dash, nothing collapsed - verified
against 2.1.269 by running a session in a directory named `slug._test x`,
which was filed as `-tmp-cmtest-slug--test-x`: the dot, the underscore and
the space each became a dash of their own. Paths with dots are ordinary on
macOS (iCloud Drive lives under `Mobile Documents`), and the old slash-only
rule pointed at a directory that does not exist, so repair-session could
not find a single transcript there.
It is also the physical directory that gets slugged. Claude Code asks the
OS for its working directory, and symlinks come back resolved: a session
started in /tmp/x is filed under -private-tmp-x on macOS, where /tmp is a
symlink, while the shell's $PWD still reads /tmp/x. Verified the same way -
a session started in /tmp/cmtest/linkdir landed under -tmp-cmtest-realdir.
cm_project_dir now applies the real rule and falls back to the resolved
path, which also covers the walk-up search in repair-session. Both cases
were re-tested end to end afterwards: from the dotted-and-spaced directory
and from the symlinked one, the transcripts are found.
The bar widget still reverses a slug for display ("-home-smoido-Work" ->
"home/smoido/Work"), which is lossy in the same way but is only a label,
and only ever sees Linux paths.
Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
+27
-2
@@ -2212,9 +2212,34 @@ cm_apply_session_action() {
|
|||||||
# Transcript repair
|
# Transcript repair
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
# ~/.claude/projects/<cwd with every slash turned into a dash>
|
# Claude Code files transcripts under ~/.claude/projects/<slug>, and the slug
|
||||||
|
# is not "slashes to dashes": *every* non-alphanumeric character becomes one
|
||||||
|
# dash, nothing collapsed. Verified against 2.1.269 - a directory named
|
||||||
|
# `slug._test x` was filed as `-tmp-cmtest-slug--test-x`, so the dot, the
|
||||||
|
# underscore and the space each became a dash of their own. Paths with a dot in
|
||||||
|
# them are ordinary on macOS (iCloud Drive sits under `Mobile Documents`), and
|
||||||
|
# a slash-only rule points at a directory that does not exist.
|
||||||
|
cm_project_slug() {
|
||||||
|
printf '%s' "$1" | sed 's|[^a-zA-Z0-9]|-|g'
|
||||||
|
}
|
||||||
|
|
||||||
|
# It is also the *physical* directory that gets slugged. Claude Code asks the OS
|
||||||
|
# for its working directory and symlinks come back resolved, so a session
|
||||||
|
# started in /tmp/x is filed under -private-tmp-x on macOS (where /tmp is a
|
||||||
|
# symlink) while the shell's $PWD still reads /tmp/x and looks in -tmp-x.
|
||||||
|
# The logical path is tried first, since that is what a user types and what a
|
||||||
|
# plain project looks like; the resolved one is the fallback.
|
||||||
cm_project_dir() {
|
cm_project_dir() {
|
||||||
printf '%s/projects/%s' "$CM_SETTINGS_DIR" "$(printf '%s' "${1:-$PWD}" | sed 's|/|-|g')"
|
local path="${1:-$PWD}" slug phys
|
||||||
|
slug="$(cm_project_slug "$path")"
|
||||||
|
if [ -d "$CM_SETTINGS_DIR/projects/$slug" ]; then
|
||||||
|
printf '%s/projects/%s' "$CM_SETTINGS_DIR" "$slug"; return 0
|
||||||
|
fi
|
||||||
|
phys="$(cd "$path" 2>/dev/null && pwd -P)" || phys=''
|
||||||
|
if [ -n "$phys" ] && [ "$phys" != "$path" ]; then
|
||||||
|
slug="$(cm_project_slug "$phys")"
|
||||||
|
fi
|
||||||
|
printf '%s/projects/%s' "$CM_SETTINGS_DIR" "$slug"
|
||||||
}
|
}
|
||||||
|
|
||||||
# Modification time as an epoch second. GNU stat spells it -c %Y, BSD/macOS
|
# Modification time as an epoch second. GNU stat spells it -c %Y, BSD/macOS
|
||||||
|
|||||||
Reference in New Issue
Block a user