Hold Option (⌥) over a Forkshop tile. Elements get a dashed
blue outline, the cursor changes to a pointer, and a small caption
shows the filename and line that produced the element. Click — your
editor opens there.
The dashed outline distinguishes opt-click from click-to-edit text, which uses a solid blue outline. Holding Option suspends the text-edit affordance, so opt-click takes precedence even on elements you could normally edit in place.
How it works
@locator/webpack-loader runs at compile time and stamps a
data-locatorjs="<file>:<line>:<col>" attribute onto every JSX
element. Forkshop's EditorLink component lives inside your app's
root layout — so it loads inside each iframed page, not in the
Forkshop shell. When the modifier is held, EditorLink listens for
clicks, reads the data-locatorjs attribute, and points
window.top at vscode://file/<abs-path>:<line>:<col>. Your OS
hands the URL to whichever app registered the vscode:// scheme.
The hover outline and filename caption are drawn by the canvas, not
by EditorLink itself — the iframe posts the hovered element's rect
and source location to the canvas via postMessage, and the canvas
renders the overlay at viewport level. This keeps the outline at a
constant on-screen thickness as you zoom and avoids the iframe's
overflow clipping when the caption extends past the tile edge.
EditorLink activates only when:
process.env.NODE_ENV === "development",- the page is rendered inside an iframe, and
- the parent's pathname starts with
/forkshop.
So the ring never appears in production and never appears on your real pages — only on tiles inside the Forkshop canvas.
Editor support
The URL scheme is vscode://file/.... That works in:
- VS Code.
- Cursor. Cursor registers the same scheme.
- VS Code Insiders. With the
vscode-insiders://handler.
Other editors (JetBrains, Zed, Neovim) aren't wired in. The fix would be a different URL scheme; the underlying click handler is small.
If clicking does nothing, your editor probably hasn't registered a
vscode:// handler with the OS. That's a one-time editor setup,
not something Forkshop can paper over.
Setup
The setup skill — run from Claude Code after forkshop init, when
you say "set up Forkshop" — adds @locator/webpack-loader to your
devDependencies, merges the loader rule into next.config.*
(including app/** so route pages get attribution), and mounts
<EditorLink /> in your root app/layout.tsx.
forkshop init itself does not wire this up. If you want it
without running the setup skill, add the loader to next.config.*
yourself and mount <EditorLink /> from @forkshop/engine in your
root layout:
import { EditorLink } from "@forkshop/engine"
export default function RootLayout({ children }) {
return (
<html>
<body>
{children}
<EditorLink mountPath="/forkshop" />
</body>
</html>
)
}
Disabling
Remove the @locator/webpack-loader entry from next.config.*
(and the dep from package.json), or remove the <EditorLink />
mount from your root layout. The hover ring disappears.