
1. Codex Desktop 预览裂图相对路径本地图片为什么加载不出来Codex Desktop 的 Markdown preview 不渲染相对路径本地图片这个问题的典型表现是你在.md里写了编辑区一切正常切到预览面板却是一张裂图控制台里躺着Failed to load resource或者Not allowed to load local resource。同一份文件丢进别的编辑器打开图片好端端地显示出来唯独 Codex Desktop 的预览器不认。这个现象说明问题不在图片本身而在「相对谁解析」。相对路径./images/arch.png本身不是一个完整地址它必须挂在一个基准地址base URL上才能算出真正的绝对位置。预览器把 Markdown 渲染成 HTML 后塞进一个内嵌 WebView如果这个 WebView 加载的是http://localhost:port/preview这类虚拟地址那么相对路径的基址就变成了http://localhost:port/跟你的.md文件真实目录毫无关系图片自然找不到。适合读这篇的人用 Codex Desktop 写技术文档、维护项目 README、做本地知识库的开发者。你会拿到可复制的 settings 片段、逐步验证动作以及一套从路径解析、工作区根目录到渲染器配置的排查链路。我试过把同一份 md 在三种基址下跑一遍结论很直接——基址一错相对路径就指向了不存在的地方。先把核心检索词摆清楚Codex Desktop 的 Markdown preview 依赖 WebView 渲染local images 能否显示取决于 relative paths 的解析基址是否正确。搞懂这一条后面所有配置都有方向。2. TaoToken 前置把模型接入配置收拢到一处在动手改预览配置之前先把模型接入这条链路理顺因为 Codex Desktop 里很多行为受 settings 影响而 settings 里往往同时管着模型端点和渲染选项。TaoToken 在这里的角色是统一的模型接入层官网地址是 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content API 入口是 https://taotoken.net/api 。你需要先拿到一个 API Key入口在 https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi_keysutm_campaignrewrite 。拿到之后Codex Desktop 的模型配置通常写在auth.json或对应的 settings 文件里三件套是 Base URL、Key、Model ID缺一不可。Base URL 填https://taotoken.net/apiKey 填你申请到的那串Model ID 按你实际要用的模型填。这里要强调一个容易混的点模型接入配置和 Markdown 预览配置是两套东西但它们在 Codex Desktop 里可能落在同一个 settings 文件的不同字段下。很多人改预览问题时顺手把模型配置也动了结果预览没修好模型请求先 401 了。所以我的建议是分两步走——先把模型接入验证通过再单独处理预览的路径解析。验证模型接入是否正常可以用模型对话页面直接测 https://taotoken.net/models?utm_sourcetaotoken_aicg_blog_endutm_contentmodelsutm_campaignrewrite 。如果那边能正常出结果说明 Base URL 和 Key 没问题问题就纯粹在预览渲染这一侧。如果你打算长期用 Codex Desktop 做编码和 Agent 任务可以考虑 Coding Plan入口在 https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding_planutm_campaignrewrite 。它适合那种每天都要跑代码生成、需要稳定额度的场景。接入文档在 https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite 配置细节以文档为准。把模型这层理顺之后我们回到预览本身。记住预览裂图跟模型没关系但 settings 文件是共用的改的时候要精准定位到渲染相关字段别误伤模型配置。3. 可复制配置settings 片段与 base href 注入这一节给可直接复制的配置。Codex Desktop 的 settings 一般是一个 JSON 文件路径因平台而异macOS 常见在~/Library/Application Support/Codex/settings.jsonWindows 在%APPDATA%\Codex\settings.jsonLinux 在~/.config/Codex/settings.json。你要先确认自己机器上的真实路径再往里加字段。先给一份模型接入 预览渲染并存的 settings 片段字段名以你本地实际版本为准重点是结构{ model: { baseUrl: https://taotoken.net/api, apiKey: sk-你的Key, modelId: 你的ModelID }, markdown: { preview: { baseHrefMode: fileDir, allowLocalFileAccess: true, resolveRelativeWithUrljoin: true, encodePath: true } } }baseHrefMode设成fileDir的意思是渲染 HTML 时把被预览.md文件所在目录作为base href写进head。这是解决相对路径裂图最关键的一步。allowLocalFileAccess放开 WebView 读本地文件的能力但要注意安全边界后面会讲。resolveRelativeWithUrljoin让相对路径用urljoin解析而不是字符串拼接encodePath处理中文和空格。如果你用的是 TOML 风格的配置部分版本支持等价写法[model] base_url https://taotoken.net/api api_key sk-你的Key model_id 你的ModelID [markdown.preview] base_href_mode fileDir allow_local_file_access true resolve_relative_with_urljoin true encode_path true配置改完Codex Desktop 需要重启预览进程才生效。有些版本是关掉预览面板再打开有些要整个应用重启实测下来重启应用最稳。再给一段渲染层注入base href的参考实现如果你在写自定义预览插件或调试渲染链路这段能直接对照import os def render_markdown_html(md_path: str, html_body: str) - str: dir_url file:// os.path.abspath(os.path.dirname(md_path)) / return f!DOCTYPE html html head meta charsetutf-8 base href{dir_url} /head body {html_body} /body /html if __name__ __main__: md /Users/me/doc/readme.md body img src./images/arch.png print(render_markdown_html(md, body))运行后你会看到base hreffile:///Users/me/doc/这样页面里所有相对路径都相对 md 目录解析裂图消失。注意末尾那个斜杠不能少少了会把最后一级目录当成文件名。如果你更倾向在后端预解析相对路径不依赖 base 标签用urljoin把相对 src 算成绝对file://再注入import os from urllib.parse import urljoin def resolve_image_src(md_dir: str, src: str) - str: if src.startswith((http://, https://, data:)): return src if src.startswith(file://): return src if os.path.isabs(src): return file:// src base file:// md_dir / return urljoin(base, src) if __name__ __main__: md_dir /Users/me/doc print(resolve_image_src(md_dir, ./images/arch.png)) print(resolve_image_src(md_dir, ../assets/logo.png)) print(resolve_image_src(md_dir, https://x.com/a.png))urljoin会自动处理./、../和多级回退比手写字符串拼接可靠得多。网络图和data:内联图原样保留不要试图把它们当本地文件解析。注意放开allowLocalFileAccess的同时一定要用commonpath把读取范围锁死在 md 目录子树内防止恶意 md 用../../etc/passwd逃逸到系统目录。安全边界不能省。4. 验证请求逐步确认图片真的加载成功配置改完不能只看「好像显示了」要逐步验证。第一步把 md 里的图片改成绝对路径如果预览能显示说明预览器本身能读本地文件问题就是相对解析。第二步改回相对路径./images/arch.png同时打开开发者工具看控制台。Codex Desktop 的预览面板一般能通过快捷键或菜单打开 DevTools看 Network 面板里图片请求的最终 URL。如果 URL 是http://localhost:port/images/arch.png说明基址还是虚拟预览地址baseHrefMode没生效。如果 URL 是file:///Users/me/doc/images/arch.png说明基址对了再看是不是被安全策略拦了。第三步检查控制台报错。Not allowed to load local resource是 WebView 拦截file://需要allowLocalFileAccess。Failed to load resource: net::ERR_FILE_NOT_FOUND是路径算错了多半是基址或编码问题。net::ERR_NAME_NOT_RESOLVED说明把本地路径当网络地址解析了检查resolveRelativeWithUrljoin是否生效。第四步用一段最小 md 做隔离测试。新建test.md内容只有一行确保images/arch.png真实存在。这样排除掉多级目录、中文路径等干扰因素。如果最小用例能显示再逐步加回复杂路径定位是哪一级出的问题。第五步验证中文和空格路径。把图片放到我的 文档/images/架构 图.png看预览是否正常。如果裂图检查encodePath是否把空格编码成%20、中文是否做了 URL 编码。部分 WebView 对未编码的非 ASCII 路径不认。第六步验证../回退。把 md 放在doc/sub/readme.md图片放在doc/images/arch.png引用写成../images/arch.png。如果这个能显示说明urljoin解析正确如果裂图说明还在用字符串拼接。每一步都记录下最终 URL 和控制台输出这样即使问题没一次解决你也能明确知道卡在哪一环。实测下来大部分裂图卡在第一步和第三步——要么基址没注入要么 file 访问被拦。5. 本篇常见错排查401、local proxy failed、reading choices、OAuth改配置过程中会遇到几类典型报错逐个对照。401 Unauthorized这是模型接入的报错不是预览的。说明apiKey填错或过期或者baseUrl写成了带路径的形式。检查 settings 里baseUrl是不是https://taotoken.net/apiKey 是不是从 https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi_keysutm_campaignrewrite 拿的那串。三件套 Base URL、Key、Model ID 要同时正确缺一个都可能 401。local proxy failed这个报错通常出现在网络层说明请求没走到目标端点。检查是不是本地有代理配置干扰或者baseUrl写成了http而不是https。如果你在 settings 里同时配了模型和预览确认改预览字段时没误删模型字段的引号或逗号JSON 语法错误也会导致整个配置加载失败表现成各种奇怪的连接问题。reading choices相关报错这是模型返回结构解析失败常见于 Model ID 填错或端点返回了非预期格式。确认modelId跟你在模型对话页面测通的那个一致。如果模型对话页面正常、Codex Desktop 里报这个多半是 settings 里的 modelId 拼写有出入。OAuth相关报错部分版本用 OAuth 流程接入如果报 OAuth 失败检查是不是同时配了 API Key 和 OAuth 两套凭证导致冲突。二选一别混用。用 API Key 方式就清掉 OAuth 相关字段。预览侧的报错再列一遍Not allowed to load local resource对应allowLocalFileAccess没开ERR_FILE_NOT_FOUND对应基址或编码错图片显示但更新后不刷新是 WebView 缓存给图片 URL 加?vmtime时间戳强制刷新。如果你用 CC Switch 或 Cline MCP 这类工具管理配置出现问题时同样要检查三件套 Base URL、Key、Model ID 是否完整。Codex 的auth.json里如果只填了 Key 没填 Base URL请求会打到默认端点表现成 401 或超时。三件套齐全是最低要求。排查顺序建议先确认模型接入正常模型对话页面能出结果再单独查预览。两件事混在一起查容易互相干扰。6. 语义一致 CTA接入、验证、长期使用各走各的入口预览修好之后如果你还想把模型接入这条链路也理顺按用途分流走对应入口别只停在首页。排障和接入配置相关去 API Keys 页面拿 Key再去接入文档对照字段 https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi_keysutm_campaignrewrite 和 https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite 。文档里有各客户端的配置样例Codex 的auth.json写法也在里面。想先验证模型能不能正常出结果用模型对话页面直接测 https://taotoken.net/models?utm_sourcetaotoken_aicg_blog_endutm_contentmodelsutm_campaignrewrite 。输入一句话看返回通了再往 Codex Desktop 里配。长期做编码、跑 Agent 任务需要稳定额度看 Coding Plan https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding_planutm_campaignrewrite 。控制台在 https://taotoken.net/console?utm_sourcetaotoken_aicg_blog_endutm_contentconsoleutm_campaignrewrite 用量和额度都在那边看。Claude Code 相关的接入配置参考 https://taotoken.net/claude-code?utm_sourcetaotoken_aicg_blog_endutm_contentclaude_codeutm_campaignrewrite 。最后回到预览这件事本身。相对路径永远相对某个基址预览器要渲染本地图基址就必须是「被预览文件真实所在目录」而不是「虚拟预览页地址」。这一条想通裂图问题基本就解决了。剩下的都是细节Windows 盘符file:///C:/...三个斜杠别写错中文空格记得编码网络图原样保留安全边界用commonpath锁死。改完配置重启应用打开 DevTools 看最终 URL一步步验证比反复猜要快得多。