fix: ClickUp task deep links, plus a rewriter-pack audit - #11
Merged
Merged
Conversation
The `clickup` rewriter captured a single path segment after `/t/`, so a workspace-scoped task URL — `app.clickup.com/t/9018159683/DEV-1234`, the form the web app puts in the address bar and the one "Copy link" gives when Custom Task IDs are on — rewrote to `clickup://t/9018159683`. That is the workspace ID, not the task, so ClickUp opened on whatever screen it was last showing. The rewrite succeeded, so the degrade-to-fallback path never engaged and the link was silently sent to the wrong place. Match the whole task path instead and hand it to the app verbatim, the way the `clickup-doc` rewriter already does. Short links keep working; a bare `/t/` still fails the rewrite and falls back to the browser. Fixes #10 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014SuMinAawh7kGt3npJe8v5
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
jnahian
marked this pull request as ready for review
August 3, 2026 12:19
…ains Audit of the whole rewriter pack, prompted by the ClickUp task bug. Two classes of problem, one much worse than the other. Silently wrong target — the rewrite succeeds, so the degrade-to-fallback path never engages and the link lands somewhere wrong instead of in a browser: - apple-music dropped the query, but a song lives at its album's address with `?i=<trackID>`. Every song link opened the album at track 1. - github-desktop treated any two-segment path as `owner/repo`, so /settings/*, /orgs/*, /features/*, /sponsors/*, /topics/* and /users/* asked GitHub Desktop to open a repository that doesn't exist. The reserved-segment list is anchored with a trailing slash so an owner may still start with one (newrelic/…). - linear matched all of linear.app, which is also Linear's marketing, docs and blog. Restricted to workspace routes; anything else falls back to the browser. Missed matches — safe, the link still opened in a browser, but the app was never offered: - teams only knew teams.microsoft.com, not the newer teams.cloud.microsoft or teams.live.com. - telegram had no pattern for a link to a single post; it opened the channel at the bottom. Reuses the shared template — `post=` is dropped by cleanEmptyParams when the pattern has no second capture. - todoist required the app. subdomain on task URLs. - discord didn't know the legacy discordapp.com. - clickup-doc kept a trailing slash in the deep link. Left alone deliberately: notion (notion.so is all workspace content now) and vscode, whose `vscode://<path>` output looks wrong but is flagged experimental and can't be checked without a Mac. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014SuMinAawh7kGt3npJe8v5
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #10, then audits the rest of the rewriter pack for the same class of bug.
1. The reported bug: ClickUp task links
The
clickuprewriter captured a single path segment after/t/, so a workspace-scoped task URL — the form the ClickUp web app puts in the address bar, and the one Copy link gives when Custom Task IDs are on — lost the task ID:That's the workspace ID, so ClickUp opened on whatever screen it was last showing. Short shared links (
/t/86cxk2m1q) were unaffected, which is why it looked intermittent. Now matches the whole task path and hands it to the app verbatim, the wayclickup-docalready does.2. The audit
The interesting part of that bug isn't the regex — it's that the rewrite succeeded. A rewriter that returns a valid-looking URL bypasses the "a link is never lost" guarantee:
RoutingEnginesees a successful rewrite,Dispatcherfinds an app for the scheme, and the link opens somewhere wrong. A rewriter that returnsnildegrades to the browser and the user just sees a browser. So the pack was checked for that specific failure first.Silently wrong target
apple-musicmusic.apple.com/us/album/blue/1440835967?i=1440836193music://…/1440835967— the album, track 1?i=, opens the songgithub-desktopgithub.com/settings/profile,/orgs/x,/features/x,/sponsors/x,/topics/x,/users/xlinearlinear.app/pricing,/docs/…,/blog/…clickup/t/<workspace>/<task>github-desktopmatched any two-segment path asowner/repo. The reserved-segment list is anchored with a trailing/so an owner may still start with a reserved word —newrelic/newrelic-ruby-agentstill works (there's a test).linearmatched all oflinear.app, which is also Linear's marketing, docs and blog. It's now an allowlist of workspace routes (issue,team,project,view,document,initiative,inbox,my-issues,settings,roadmap,cycle,label,search,triage,active,backlog). An allowlist rather than a blocklist because the marketing routes grow and the app routes don't — and an unknown route degrading to the browser is the safe direction.Missed matches
Safe (the link opened in a browser), but the app was never offered:
teams— only knewteams.microsoft.com, not the newerteams.cloud.microsoftorteams.live.com.telegram— no pattern for a link to a single post (t.me/durov/123); it opened the channel at the bottom. Reuses the shared template:post=is dropped bycleanEmptyParamswhen the matching pattern has no second capture, the same trickzoomuses forpwd.todoist— required theapp.subdomain on task URLs.discord— didn't know the legacydiscordapp.com.clickup-doc— kept a trailing slash in the deep link.Left alone deliberately
notionmatches all ofnotion.so. Notion's marketing lives onnotion.comnow, so the over-match is theoretical.vscodeturnsgithub.dev/o/rintovscode://o/r, which doesn't look like a valid VS Code URI (those arevscode://<extension-id>/…). It's flagged experimental in its own name and I can't check the real behavior without a Mac, so I didn't guess at a replacement. Worth a look.app.clickup.com/9018159683/v/li/…) still have no rewriter. That's a new rewriter rather than a fix — the follow-up noted in ClickUp deep link opens the wrong screen for task URLs copied from Chrome (/t/<workspaceId>/<taskId>) #10.Changes
Sources/JunctionCore/Resources/rewriters.json— 9 rewriters touched, patterns and two templates.Tests/JunctionCoreTests/TransformTests.swift— 8 new/extended tests covering each fix and the non-matches that must stay non-matches.CHANGELOG.md—Fixed:entries under## Unreleased, one per user-visible change.No docs change: the deep-link app list on the website is generated from
rewriters.jsonat build time, and no rule field, CLI flag, or Settings screen moved.Verification
zoom,spotify,slack,slack-channel,figma,notion,whatsapp,asana,app-store). All pass.cd web && npm test && npm run build— pass.rewriters.jsonschema/regex validator, run locally — pass, 19 rewriters.swift testnot run — no Swift toolchain in this Linux container. CI runs it on macOS and Linux. The changes are data-only and the new tests exercise the bundled pack, but they are unexecuted here.