Problem
Clicking a markdown file link that starts with ~/ does nothing. Example link in chat:
[~/Documents/CraftAgents/note.md](~/Documents/CraftAgents/note.md)
The same link with an absolute path (/Users/me/Documents/...) opens correctly.
Root cause
The tilde is never expanded before being handed to Electron's shell.openPath, which does not do shell-style ~ expansion. The error returned by openPath is swallowed by .then(() => {}), so the click appears to silently do nothing.
Trace through the code:
packages/ui/src/components/markdown/linkify.ts — FILE_PATH_TARGET_REGEX explicitly matches ~/ paths, so isFilePathTarget('~/foo.md') is true.
packages/ui/src/components/markdown/link-target.ts — resolveMarkdownLinkTarget returns { kind: 'file', path: '~/foo.md' } unchanged.
packages/ui/src/components/markdown/Markdown.tsx — the a component calls onFileClick('~/foo.md').
apps/electron/src/main/platform.ts:
openPath: (p) => shell.openPath(p).then(() => {}),
shell.openPath receives ~/foo.md literally. It returns a non-empty error string ("Failed to open path"), which is discarded.
Steps to reproduce
- In any chat turn, have the agent output a markdown link with a
~/ path to an existing file, e.g. [~/Documents/test.md](~/Documents/test.md).
- Click the link.
- Nothing happens. No error, no toast, no file opens.
- Replacing
~/ with the full home path makes the same link work.
Expected
Either:
- The tilde is expanded to the user's home directory before
shell.openPath, and the file opens, or
- If opening fails, a visible error (toast/log) is shown instead of silently swallowing it.
Suggested fix
Expand ~ to os.homedir() in one of:
resolveMarkdownLinkTarget (renderer-side, UI package), or
- the Electron main-process
openPath wrapper in apps/electron/src/main/platform.ts.
The second option also fixes any other call site that passes ~/... to openPath. Consider also surfacing the error string from shell.openPath instead of discarding it.
Environment
- Craft Agents 0.8.9
- macOS 15 (Darwin 25.3.0), arm64
Related
Problem
Clicking a markdown file link that starts with
~/does nothing. Example link in chat:The same link with an absolute path (
/Users/me/Documents/...) opens correctly.Root cause
The tilde is never expanded before being handed to Electron's
shell.openPath, which does not do shell-style~expansion. The error returned byopenPathis swallowed by.then(() => {}), so the click appears to silently do nothing.Trace through the code:
packages/ui/src/components/markdown/linkify.ts—FILE_PATH_TARGET_REGEXexplicitly matches~/paths, soisFilePathTarget('~/foo.md')istrue.packages/ui/src/components/markdown/link-target.ts—resolveMarkdownLinkTargetreturns{ kind: 'file', path: '~/foo.md' }unchanged.packages/ui/src/components/markdown/Markdown.tsx— theacomponent callsonFileClick('~/foo.md').apps/electron/src/main/platform.ts:shell.openPathreceives~/foo.mdliterally. It returns a non-empty error string ("Failed to open path"), which is discarded.Steps to reproduce
~/path to an existing file, e.g.[~/Documents/test.md](~/Documents/test.md).~/with the full home path makes the same link work.Expected
Either:
shell.openPath, and the file opens, orSuggested fix
Expand
~toos.homedir()in one of:resolveMarkdownLinkTarget(renderer-side, UI package), oropenPathwrapper inapps/electron/src/main/platform.ts.The second option also fixes any other call site that passes
~/...toopenPath. Consider also surfacing the error string fromshell.openPathinstead of discarding it.Environment
Related
openPath); different root cause but same code path.