Skip to content

feat: reopen URLs with Preferis through the preferis: scheme - #52

Merged
mayuki merged 2 commits into
mainfrom
claude/preferis-url-scheme-2928a5
Nov 2, 2026
Merged

mayuki merged 2 commits into
mainfrom
claude/preferis-url-scheme-2928a5

Conversation

@mayuki

@mayuki mayuki commented Nov 2, 2026 •

Copy link
Copy Markdown
Member

Summary

Adds the preferis: URL scheme. A browser (a bookmarklet, an extension) or any app that can open URLs hands a URL back to Preferis, which routes it with the rules like any other link. It works without Preferis being the default browser.

Form Example
preferis://open?url=<percent-encoded URL> preferis://open?url=https%3A%2F%2Fexample.com%2F%3Fq%3D1
preferis:<URL> preferis:https://example.com/?q=1

Bookmarklet:

javascript:location.href='preferis://open?url='+encodeURIComponent(location.href)

Taking the URL out (Core.Routing.ReopenUrl)

  • The two forms are told apart by whether // follows preferis:. The scheme and the open action are case-insensitive.
  • Only http and https URLs are carried. Web pages can open preferis: URLs, and a file: URL or another scheme could reach the system default handler (ShellExecute on Windows) through the system action or a fallback, which would start a program. A nested preferis: URL is refused by the same rule, so nothing loops.
  • The open form refuses parameters besides url, a second url and a fragment. A URL that was not encoded would otherwise open cut short at its first & or #. Values are percent-decoded only: + stays +.

Routing (RoutingService.Handle(string))

  • The URL taken out is routed as any other. The app that opened it (appId / appPath) is the app that opened the preferis: URL, usually the browser, so a rule can send pages coming back from Chrome to Firefox.
  • The history records the URL taken out (HandleResult.Url).
  • When no URL can be taken out, the Router logs why with the input masked, and shows it in a message box in the configured language. The reason never repeats the input, which may hold a token. Other input that is no URL at all is still only logged.
  • --dry-run and the test page of the settings route the URL taken out too.

Registration

  • Windows: --register writes HKCU\Software\Classes\preferis (URL Protocol, "<Preferis.exe>" --single-argument %1), and --unregister removes it. Only Preferis handles the scheme, so it is not among the URLAssociations and nothing is chosen in Settings.
  • Windows, existing installations: a registration whose preferis key is missing or points elsewhere counts as not registered. After the update, the settings offer Make Default again. It re-registers and, when http / https already are Preferis, does not open the Settings page.
  • macOS: the Router's Info.plist declares preferis in its own CFBundleURLTypes entry. Launch Services delivers it as an Apple Event, like http / https.

Docs

  • docs/Design.ja.md §5.5 (new), §4.3, §5.1, §10, §13
  • docs/Platform.ja.md §2.2, §3.1
  • New site page reopen-with-preferis in English and Japanese

Test plan

  • dotnet test Preferis.Windows.slnf -p:Platform=x64: Core 651, Platform 133, Settings.Core 247, all passed. dotnet build of the filter has 0 warnings.
  • Preferis.exe --dry-run with both forms routes the URL inside, and refuses a file: URL and an unencoded open URL.
  • Windows: after Make Default, a preferis: link or the bookmarklet in a browser opens the URL inside it through the rules
  • macOS: build, then open a preferis: URL from a browser and with open 'preferis:https://example.com/'
  • Documentation site build

🤖 Generated with Claude Code

mayuki and others added 2 commits November 2, 2026 18:14
Add the preferis: URL scheme, so that a browser (a bookmarklet, an
extension) or any app that can open URLs hands a URL back to Preferis to
route with the rules. Two forms are accepted:

- preferis://open?url=<percent-encoded URL>
- preferis:<URL>, with the URL as it is

Only http and https URLs are carried: web pages can open preferis: URLs,
and another scheme could reach the system default handler through the
rules and start a program. The open form refuses anything besides its url
parameter, so that a URL that was not encoded is not opened cut short at
its first & or #. When no URL can be taken out, the Router logs why (input
masked) and shows it in a message box in the configured language.

The URL taken out is routed as any other, as opened by the app that opened
the preferis: URL, and is what the history records. --dry-run and the test
page of the settings route it too.

Windows registers HKCU\Software\Classes\preferis with --register (and
removes it with --unregister); a registration without it counts as not
registered, so the settings offer Make Default to an older registration.
macOS declares the scheme in the Router's CFBundleURLTypes.

Documented in Design.ja.md §5.5 and Platform.ja.md §2.2 / §3.1, and on a
new page of the documentation site in English and Japanese.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@mayuki
mayuki merged commit b8d859e into main Nov 2, 2026
5 checks passed
@mayuki
mayuki deleted the claude/preferis-url-scheme-2928a5 branch November 2, 2026 09:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant