Codex Desktop: support deep links to Markdown headings from chat and rendered docs
Bug / Feature Request
Codex Desktop renders local Markdown file links from chat well enough to open the target file, but heading anchors do not appear to work.
For example, a chat link to:
C:/Users/chris/GitHub/service-gpt-copy-paste/gpt/models/container-part.model.md#preconditions
opens the Markdown file, but does not navigate to the ## Preconditions heading. The same problem appears inside rendered Markdown docs themselves: links from a table of contents to headings in the same document do not jump to the target section.
Expected Behavior
Markdown links with heading fragments should navigate to the heading target:
- From Codex chat into a local Markdown file heading.
- From one local Markdown doc to another local Markdown doc heading.
- From a local Markdown doc to a heading in the same rendered doc.
Actual Behavior
The file opens, but the #heading-fragment is ignored.
Why This Matters
We are using gpt/models/*.md files as durable design models and commit-note references. Codex chat can already provide useful clickable file links, but without heading support, model docs become harder to navigate as they grow.
This would make model-heavy workflows much better: Codex could draft a note in chat with deep links to exact model sections, then publish those same links into the docs.
Example Workflow
A commit note includes links to sections such as:
- Container Part Model
- Preconditions
- STL Name Basis
- STL Argument Order
- JS Overload Names
- Member Index
- Lexeme Index
Each item should link directly to its section in gpt/models/container-part.model.md.
Environment
- Codex Desktop app
- Windows
- Local workspace Markdown files
- Links generated from Codex chat and from rendered Markdown docs
2 Comments
Fix: Deep Links to Markdown Headings
Issue: openai/codex #24383
Severity: Medium — broken navigation in rendered Markdown
Labels:
bug,app,enhancementStatus: OPEN (0 comments)
---
1. Root Cause Analysis
1.1 Symptom
Codex Desktop renders local Markdown file links from chat, but heading anchors do not work. For example:
C:/Users/chris/GitHub/project/gpt/models/container-part.model.md#preconditions## PreconditionsheadingThe same problem appears inside rendered Markdown docs: links from a table of contents to headings within the same file do not scroll to the target.
1.2 Architecture Context
Codex Desktop uses an Electron-based renderer for Markdown files. The rendering pipeline:
The anchor navigation step is either missing or broken.
1.3 Root Cause
The Markdown renderer likely:
#anchorfragmentCommon heading ID formats:
#preconditions(lowercase, spaces → hyphens)#preconditions(similar)---
2. Step-by-Step Fix Approach
2.1 Parse Anchor Fragment from Link
2.2 Navigate to Anchor After File Load
2.3 Generate Consistent Heading IDs
2.4 Handle Internal Links in Rendered Markdown
2.5 Add CSS for Heading Highlight
---
3. Testing Strategy
3.1 Unit Tests
3.2 Integration Tests
#headinganchor3.3 Regression Tests
#in directory names are handled correctly---
4. Impact Assessment
4.1 User Impact
4.2 Code Risk
4.3 Security
4.4 Files Modified
packages/desktop/src/markdown/link-handler.ts(new)packages/desktop/src/markdown/heading-ids.ts(new)packages/desktop/src/markdown/internal-links.ts(new)packages/desktop/src/markdown/renderer.ts— integrate anchor navigationpackages/desktop/src/styles/headings.css(new)packages/desktop/src/__tests__/heading-navigation.test.ts(new)---
5. Alternative Approaches Considered
---
Solution prepared for openai/codex #24383
I checked current
mainfor the Rust-side Markdown/local-file-link rendering path. One relevant normalization point iscodex-rs/tui/src/markdown_render.rs:render_local_link_target()callsparse_local_link_target(), which separates supported line/column targets such as#L..,#L..C.., ranges, and:line[:col]suffixes from local file links. The surrounding tests incodex-rs/tui/src/markdown_render_tests.rscover those line/column cases.For a
file://heading fragment likefile:///.../container-part.model.md#preconditions, that path does not currently preservepreconditionsas a rendered location suffix.normalize_hash_location_suffix_fragment()only accepts line-style fragments, so non-line fragments are not treated as location targets in this renderer.A narrow regression test would be to add a local Markdown link case with a non-line
file://hash fragment, then decide whether the rendered/local-link contract should preserve that fragment as a heading target rather than dropping it. That would not cover the whole Desktop document viewer by itself, but it looks like a useful Rust-side boundary to pin down before wiring same-document and cross-document heading navigation.