Hyperlinks make it easy for devs to view source code in a browser, but don't make it easy to edit source. Hyperlinks for your editor (or IDE) that open on the right line. That's Sorcery!
Sorcery Desktop is an open source tool, built on the open-source srcuri:// (pronounced Sorcery) protocol.
Sorcery Desktop provides the local protocol handler component for srcuri:// links. It routes srcuri:// protocol links to your editor or IDE of choice.
Goal:
- Make source code editor links possible, and everywhere
Use-cases:
- Open terminal links from file paths in the terminal, or from srcuri:// links
What's it do:
- Sorcery Desktop - Makes srcuri links open in your editor, right to the file/line
- Sorcery Chrome Extension - Makes stack traces, and file paths in the browser command-clickable so they open in editor.
You just stare at the code, looking through the window. You can't
- run it
- add breakpoints
- compile it
- use your vim hotkeys
- use your LLM to analyze it
No Longer!
Sorcery uses the srcuri:// protocol to link to lines of code in your editor. Now, your coworker shares:
srcuri://reponame/path/to/file.js:53
With one click, you're on that line in your local editor and repo.
How it works:
An editor agnostic protocol backed by Sorcery Desktop - a Free, Open Source, MIT Licensed launcher you install locally.
- Open Source, MIT Licensed
- In Rust to keep memory usage small
- editor-agnostic deep link handler
Instead of:
https://github.com/user/myrepo/blob/main/src/main.rs#L42
Use:
srcuri://myrepo/src/main.rs:42
When clicked, this opens src/main.rs at line 42 in your preferred editor - whether that's VS Code, IntelliJ IDEA, Neovim, Vim, Emacs, Sublime Text, or any other supported editor.
Workspace matching. Sorcery maps your srcuri links to the matching workspace on your machine.
- Editor-agnostic: Works with 15+ editors out of the box
- Cross-platform: macOS, Windows, and Linux support
- Smart editor detection: Automatically finds installed editors and tracks which you use most
- Toolbox-aware: Seamlessly handles JetBrains Toolbox installations with auto-updates
- Session reuse: Reuses existing editor sessions when possible (e.g., Neovim sockets)
- Zero configuration: Works out of the box with sensible defaults
- MIT licensed: Free and open source
- Visual Studio Code
- VSCodium
- Cursor
- IntelliJ IDEA (Community & Ultimate)
- RubyMine
- PyCharm
- WebStorm
- GoLand
- PhpStorm
- CLion
- Rider
- RustRover
- DataGrip
- AppCode
- Neovim (with socket-based session reuse)
- Vim
- Emacs (via emacsclient)
- Sublime Text
- Zed
The Sorcery Server (available separately at github.com/ebeland/sorcery-server) provides a web gateway that enables srcuri links to work in contexts where custom protocols face limitations (Jira, Slack, web browsers).
How it works:
https://srcuri.com/open#src/main.rs:42?workspace=myrepo
When clicked, the web page parses the URL fragment and redirects to:
srcuri://myrepo/src/main.rs:42
Sorcery Desktop then opens your editor to that exact file and line.
Key features:
- Fragment-based URLs (paths never sent to server)
- Enterprise subdomain support for multi-tenant deployments
- Tenant-specific configuration via
/.well-known/srcuri.json - Dockerized for easy cloud deployment
- AGPL licensed
Sorcery Desktop is built with Tauri/Rust to keep it lightweight. It sits in the system tray while running.
Key features per editor type:
VS Code Family (vscode.rs):
- Detects VS Code, VSCodium, and Cursor
- Uses CLI flags:
--goto <file>:<line>:<column> - Reuses existing windows by default
JetBrains IDEs (jetbrains.rs):
- Unified manager for all JetBrains products
- Toolbox-aware with mtime-based version selection
- Handles both standalone and Toolbox installations
- Auto-retry on launch failure with cache invalidation
- Platform-specific launching:
- macOS:
open -n -a <app> --args --line <num> <file> - Windows:
cmd.exe /c start "" <exe> --line <num> <file> - Linux: Direct execution with detached process
- macOS:
- 5-minute binary cache TTL
Terminal Editors (terminal.rs):
- Neovim: Socket discovery and reuse via
nvim --server- Recursively searches
/tmpand$TMPDIRfor sockets - Matches socket to workspace via
getcwd() - Falls back to new terminal window if no socket found
- Recursively searches
- Vim: Opens in Terminal.app via AppleScript
- Emacs: Uses
emacsclientfor session reuse
- Polls every 10 seconds to detect frontmost application
- Uses platform-specific APIs:
- macOS: NSWorkspace
- Windows: GetForegroundWindow
- Linux: X11/Wayland detection
- Maps process names to editor IDs
- Updates last-seen timestamps
- Routes
open()requests to appropriate editor - Validates paths before opening
- Determines editor selection:
- Explicit editor hint from request
- Workspace-specific preference
- Most recently used editor
- First available editor
- Handles errors and provides user feedback
1. Deep link clicked: srcuri://project/file.rs:42
↓
2. OS routes to sorcery application
↓
3. Dispatcher.open(file, line, column, hint)
↓
4. PathValidator.validate(file)
↓
5. EditorDispatcher.determine_editor(workspace, hint)
↓
6. EditorManager.open(file, OpenOptions)
↓
7. Platform-specific launch command
↓
8. Editor opens file at specified location
The JetBrains manager implements sophisticated discovery and launching:
Binary Discovery (macOS example):
- Check cache (5-minute TTL)
- Look for standalone
.appin/Applicationsand~/Applications - Search Toolbox installations:
~/Library/Application Support/JetBrains/Toolbox/apps/<product>/- Check
ch-0(stable) thench-1(EAP) - Sort versions by modification time (newest first)
- Return full
.apppath (not internal CLI script)
- Heuristic fallback: search all Toolbox products for matching
.app - Cache result (or null) for 5 minutes
Launch Strategy:
- macOS uses
open -n -ato force new instance (required for argument passing) - Without
-n, macOS activates existing instance and ignores arguments - Arguments passed as:
--line <num> <file>(not<file>:<line>)
Auto-retry on Failure:
let result = spawn_editor(binary, args);
if result.is_err() {
cache.invalidate();
if let Some(new_binary) = find_binary() {
return spawn_editor(new_binary, args);
}
}This handles Toolbox updates seamlessly - if the cached binary is deleted, we rediscover it.
Neovim integration uses Unix domain sockets for IPC:
-
Socket Discovery: Recursively search
/tmpand$TMPDIRup to 2 levels deep- Example:
$TMPDIR/nvim.user/aKHN7l/nvim.79673.0 - Filters for socket file type using
FileTypeExt::is_socket()
- Example:
-
Workspace Matching: For each socket, query current directory:
nvim --server <socket> --remote-expr "getcwd()"Match target file path against nvim's cwd to find best session.
-
File Opening: Send commands via remote protocol:
nvim --server <socket> --remote-send ":{line}<CR>:e {file}<CR>"Path escaping: backslashes →
\\, spaces →\ -
Fallback: If no socket found, spawn new instance in Terminal.app
# macOS - Build, install to /Applications, and register protocol
./install-local.sh
# For faster iterations (just updates the binary, no full rebuild)
./install-dev.sh
# Manual steps
cd src-tauri
cargo build # Build debug version
cargo tauri build --debug # Create app bundleThe install scripts will:
- Build the application
- Kill any running instances
- Copy to
/Applications/Sorcery Desktop.app - Register the
srcuri://protocol handler
See DEVELOPMENT.md for detailed development instructions.
- Rust 1.70+
- Node.js 18+
- Platform-specific:
- macOS: Xcode Command Line Tools
- Windows: Visual Studio Build Tools
- Linux: webkit2gtk, libayatana-appindicator
# Install dependencies
cd src-tauri
cargo build --release
# Development mode with hot reload
npm install
npm run tauri dev
# Production build
npm run tauri buildThe application includes a built-in testbed UI for testing editor integrations:
- Run
cargo runornpm run tauri dev - Testbed window opens automatically
- Select editor and test file opening
- View debug output in terminal
Settings are stored in:
- macOS:
~/Library/Application Support/sorcery-desktop/settings.yaml - Windows:
%APPDATA%\sorcery-desktop\settings.yaml - Linux:
~/.config/sorcery-desktop/settings.yaml
Example settings:
defaults:
editor: vscode
allow_non_workspace_files: false
preferred_terminal: auto
repo_base_dir: ~/code
auto_switch_clean_branches: true
workspaces:
- path: ~/code/rust-project
name: rust-project
editor: idea
- path: ~/code/web-project
name: web-project
editor: cursorThe srcuri protocol (also known as the "Sorcery protocol") uses this format:
srcuri://<authority>/<path>:<line>:<column>?editor=<editor-id>
authority: Workspace name (default) or reserved token (wks,rel,any,abs,ext)path: Relative path for workspace modes, search path forrel/any, or absolute path forabsline: Optional line number (1-indexed)column: Optional column number (1-indexed)editor: Optional editor hint (overrides preferences)
Examples:
srcuri://myapp/src/main.rs:42
srcuri://any/src/main.rs:42
srcuri://abs/etc/hosts:1
srcuri://webapp/index.ts:10:5?editor=cursor
srcuri://backend/api/handler.go:100?editor=goland
In addition to files, srcuri:// links can open folders in most editors:
srcuri://myapp/src/controllers # Open a folder within a workspace
srcuri://abs/Users/dev/projects/myapp # Open an absolute folder path
Most editors (22 of 26) support opening folders. Line/column numbers are silently ignored for folders.
For the full protocol specification, see srcuri.com
MIT License - see LICENSE for details.
Contributions welcome! Areas of interest:
- Additional editor integrations
- Windows/Linux testing and fixes
- Deep link protocol enhancements
- UI/UX improvements
- Website: srcuri.com
- Protocol Spec: srcuri.com
- Server: github.com/ebeland/sorcery-server
- Chrome Extension: github.com/ebeland/sorcery-chrome
Built from the ground up in Rust with Tauri for better performance, maintainability, and cross-platform support.