openai/codex-plugin-cc · error · Error
Codex can import Claude sessions only from ${CLAUDE_PROJECTS
Error message
Codex can import Claude sessions only from ${CLAUDE_PROJECTS_DIR}: ${source} What it means
Thrown by resolveClaudeSessionPath as a path-traversal / sandbox guard. After realpathSync resolves both the source and ~/.claude/projects, it computes path.relative(projects, source); if the result is '', '..', starts with '..'+sep, or is absolute, the source lies outside the allowed projects directory and is rejected. Only transcripts physically under ~/.claude/projects may be imported.
Source
Thrown at plugins/codex/scripts/lib/claude-session-transfer.mjs:41
throw new Error("Could not identify the current Claude transcript. Retry with --source <path-to-claude-jsonl>.");
}
const sourcePath = resolveUserPath(cwd, requestedPath);
if (path.extname(sourcePath) !== ".jsonl") {
throw new Error(`Claude session source must be a JSONL file: ${sourcePath}`);
}
let source;
let projects;
try {
source = fs.realpathSync(sourcePath);
projects = fs.realpathSync(CLAUDE_PROJECTS_DIR);
} catch {
throw new Error(`Claude session file not found: ${sourcePath}`);
}
const relative = path.relative(projects, source);
if (relative === "" || relative === ".." || relative.startsWith(`..${path.sep}`) || path.isAbsolute(relative)) {
throw new Error(`Codex can import Claude sessions only from ${CLAUDE_PROJECTS_DIR}: ${source}`);
}
return source;
}
View on GitHub (pinned to db52e28f4d)
Solutions
- Place (or symlink) the transcript physically inside ~/.claude/projects/<encoded-cwd>/ and pass that path.
- If you have a transcript elsewhere, copy it into the projects dir rather than referencing an external location.
- Resolve symlinks yourself and confirm path.relative(os.homedir()+'/.claude/projects', realpath) does not start with '..'.
- Ensure the encoded project directory name matches Claude's convention (cwd path with separators replaced).
Example fix
// before
resolveClaudeSessionPath(cwd, { source: '/tmp/exported-session.jsonl' }) // throws (outside projects)
// after
// copy into the allowed projects dir:
// cp /tmp/exported-session.jsonl ~/.claude/projects/-tmp-myapp/session.jsonl
resolveClaudeSessionPath(cwd, { source: '~/.claude/projects/-tmp-myapp/session.jsonl' }) Defensive patterns
Strategy: validation
Validate before calling
import fs from 'node:fs';
import path from 'node:path';
import os from 'node:os';
function assertInsideProjects(p) {
const projects = fs.realpathSync(path.join(os.homedir(), '.claude', 'projects'));
const real = fs.realpathSync(p);
const rel = path.relative(projects, real);
if (rel === '' || rel === '..' || rel.startsWith(`..${path.sep}`) || path.isAbsolute(rel)) {
throw new Error(`Transcript must live under ${projects}`);
}
} Type guard
null
Try / catch
null
Prevention
- Only import transcripts physically located under ~/.claude/projects.
- Copy external transcripts into the projects dir rather than referencing them in place.
- Beware symlinks whose realpath escapes the projects root.
- Match the encoded project subdir naming Claude uses.
When it happens
Trigger: Passing a source that resolves (via symlink or absolute path) outside ~/.claude/projects, e.g. /tmp/session.jsonl, /etc/something, or a symlink under projects that points elsewhere. The relative computation escapes the projects root.
Common situations: User copies a transcript to /tmp for convenience and points --source there. A symlinked transcript whose realpath target is outside projects. Attempting to import from a custom backup directory. The encoded projects subdir name does not match, so the relative path begins with '..'.
Related errors
- Claude session file not found: ${sourcePath}
- Could not identify the current Claude transcript. Retry with
- Claude session source must be a JSONL file: ${sourcePath}
- A Claude session source path is required.
- This Codex version does not support Claude session transfer.
AI-assisted analysis of openai/codex-plugin-cc@db52e28f4d (2026-08-13).
Data as JSON: /api/errors/155d78064da5245c.
Report an issue: GitHub.