Deeplink Discovery
Use this skill from the repository root. The Python extractor is the deterministic first pass; agent-led source inspection is the second pass; web research is the enhancement pass for documented examples, parameters, and version drift.
Workflow
- Run the extractor for the target app:
python3 scripts/extract_deeplinks.py "<App Name>" --format json
- If the app exists and declares custom schemes, run the optional bundle string scan:
python3 scripts/extract_deeplinks.py "<App Name>" --scan-bundle --scan-unregistered
- Inspect source or bundle internals for route handlers and examples. Start with focused searches:
rg -n "deeplink|deep link|URLScheme|CFBundleURLSchemes|registerUriHandler|handleUri|openExternal|protocol|scheme|route" "<App.app>/Contents"
rg -n "[A-Za-z][A-Za-z0-9+.-]{1,63}://" "<App.app>/Contents"
For Electron apps, inspect packed archives too.
rg -acan find literal strings inapp.asar, but parsing the ASAR header gives cleaner evidence when output is noisy. Search both full schemes and route-parser branches such asswitch,case,kind,host,pathname, and accepted query parameter names.Follow promising hits into nearby source. For minified JavaScript, search for route fragments such as
/open,/settings,/callback,command,workspace,install,auth,join,file,threads/new,plugins/install,oauth_callback,mcp-auth-callback,magic-link, andshared-artifact.Search the web for documentation and examples before finalizing important app sections. Prefer official docs, then open-source repos/issues, then community posts.
Promote only useful non-web custom deeplinks into
README.md. Skiphttp://andhttps://schemes as catalog rows, but allow them inside query parameter values when the custom scheme requires that.Categorize each app by app type and platform. Use
macOS (installed)for local bundle evidence, and addiOS,Android,Windows, orLinuxonly when official docs, source, or credible app evidence support it.
Web Enhancement Pass
Use web search to enrich local findings with documented parameters, examples, aliases, and caveats:
"<scheme>://" "<App Name>" deeplink
"<scheme>://" "<App Name>" "URL scheme"
site:<official-domain> "<scheme>://"
site:github.com "<scheme>://" "<App Name>"
Current high-value official sources:
- Claude Desktop: https://support.claude.com/en/articles/14729294-open-claude-desktop-with-a-link
- Codex app: https://developers.openai.com/codex/app/commands
- Cursor: https://cursor.com/docs/reference/deeplinks
- Slack: https://docs.slack.dev/interactivity/deep-linking/
- Raycast: https://developers.raycast.com/information/lifecycle/deeplinks
- Apple Shortcuts open/create: https://support.apple.com/guide/shortcuts/open-create-and-run-a-shortcut-apda283236d7/ios
- Apple Shortcuts run: https://support.apple.com/guide/shortcuts/run-a-shortcut-from-a-url-apd624386f42/ios
- Apple FaceTime: https://developer.apple.com/library/archive/featuredarticles/iPhoneURLScheme_Reference/FacetimeLinks/FacetimeLinks.html
- Apple SMS: https://developer.apple.com/library/archive/featuredarticles/iPhoneURLScheme_Reference/SMSLinks/SMSLinks.html
- Apple Phone: https://developer.apple.com/library/archive/featuredarticles/iPhoneURLScheme_Reference/PhoneLinks/PhoneLinks.html
- Apple Mail: https://developer.apple.com/library/archive/featuredarticles/iPhoneURLScheme_Reference/MailLinks/MailLinks.html
- Spotify URI docs: https://developer.spotify.com/documentation/web-api/concepts/spotify-uris-ids
- Chrome for iOS: https://chromium.googlesource.com/chromium/src/+/main/docs/ios/opening_links.md
Web evidence rules:
- Official docs can promote a route from
candidatetodocumentedeven when local minified code is hard to read. - If local bundle evidence and official docs disagree, note version skew and prefer the installed app when cataloging this machine; prefer official docs when cataloging current public support.
- Treat GitHub issues, snippets, blog posts, screenshots, and forum posts as leads unless confirmed by bundle/source or official docs.
- Replace real tokens, auth codes, session IDs, file paths, and account identifiers with placeholders.
- Do not add plain
http://orhttps://rows. HTTPS may appear inside a parameter value, such asimageUrl=<https-image-url>, when the custom scheme requires it. - Remember that valid app links are not always
scheme://...: Spotify usesspotify:<type>:<id>, SMS usessms:<phone-number>, Phone usestel:<phone-number>, Mail usesmailto:<email>, and System Settings usesx-apple.systempreferences:<pane-id>.
Codebase Learnings
Info.plist usually proves only scheme ownership. Route templates usually live in minified JavaScript, Electron ASAR files, native binaries, or helper bundles.
Claude Desktop:
- Start in
/Applications/Claude.app/Contents/Resources/ion-dist. - Search
ion-dist/assetsandion-dist/i18nfor literal builders such asclaude://cowork/new,claude://code/new,claude://login/google-auth,claude://claude.ai/magic-link,claude://claude.ai/sso-callback, andclaude://cowork/shared-artifact. - Look for generic route bridges that convert browser paths into
claude://claude.ai/<path>. A bridge likedeepLinkUrl ?? claude://claude.ai/${route}${query}implies families such as chat, project, settings, admin-settings, customize, create, task, space, local_sessions, and claude-code-desktop when those web routes exist. - Search for query allowlists such as
["q","prompt","prompt_url","folder","file","repo"]to learn accepted parameters.
Codex app:
rg -afinds a few literal strings in/Applications/Codex.app/Contents/Resources/app.asarand/Applications/Codex.app/Contents/Resources/codex, but direct binary output is noisy.- Parse
app.asarand inspect virtual files containingcodex://,threads/new,oauth_callback,pluginInstall,petInstall,localConversation, orapplyCodexAppConfig. - The useful route parser pattern includes constants like
TB=\codex:`, aswitchonURL.host, and handlers forplugins,pets,automations,codex-app,connector,new,settings,skills, andthreads`. - Accepted Codex query names found in the parser include
prompt,originUrl,path,marketplace,marketplacePath,mode,name,description,imageUrl,hostId,source, andreturnTo. - Official docs currently document
codex://threads/new,codex://new?<query>,codex://threads/<thread-id>,codex://settings[/browser-use|/computer-use/google-chrome|/connections],codex://skills,codex://automations, plugin install/detail/local-plugin links, and pet install links.
Electron ASAR Notes
When a route appears in app.asar, prefer extracting snippets from the virtual file that contains the parser instead of pasting binary rg output. The useful Codex pattern was:
python3 - <<'PY'
from pathlib import Path
import json, struct
asar = Path("/Applications/Codex.app/Contents/Resources/app.asar")
blob = asar.read_bytes()
_, _, _, json_len = struct.unpack("<IIII", blob[:16])
header = json.loads(blob[16:16 + json_len])
base = 16 + ((json_len + 3) // 4) * 4
def walk(node, prefix=""):
for name, entry in node.get("files", {}).items():
path = f"{prefix}/{name}" if prefix else name
if "files" in entry:
yield from walk(entry, path)
elif "offset" in entry:
yield path, int(entry["offset"]), int(entry["size"])
for path, offset, size in walk(header):
chunk = blob[base + offset:base + offset + size]
if b"codex://" in chunk or b"threads/new" in chunk or b"oauth_callback" in chunk:
print(path)
PY
Evidence Rules
- Prefer
CFBundleURLTypesfor scheme ownership. - Treat bundle/source string matches as candidates until manually verified, documented, or clearly tied to a handler.
- Use description wording to reflect evidence quality when needed:
Opens settings.for verified/documented routes,Candidate session resume route.for unconfirmed routes. - Replace private values with placeholders such as
<workspace-id>,<channel-id>,<repo-owner>,<absolute-path>, and<token>. - Do not add auth callback URLs containing real
code,state, token, session, or account values. - Do not add destructive routes unless the description clearly warns that the link should not be opened casually.
README Row Shape
Every app entry must keep this table shape:
### App Name
- Category: Developer Tools
- Platforms: macOS (installed), iOS (documented)
- Bundle ID: `com.example.app`
- Source app: `/Applications/App Name.app`
- Evidence: local `Info.plist`; official docs
| Deeplink format | Example link | Description |
| --- | --- | --- |
| `app://<route>` | [`app://example`](https://f.github.io/awesome-deeplinks/open.html?url=app%3A%2F%2Fexample) | What this route does and how it was verified. |
| `app:<value>` | [`app:value`](https://f.github.io/awesome-deeplinks/open.html?url=app%3Avalue) | What this non-`//` route does and how it was verified. |
Example links should be clickable code links through the repo opener: [`app://example`](https://f.github.io/awesome-deeplinks/open.html?url=app%3A%2F%2Fexample) and [`app:value`](https://f.github.io/awesome-deeplinks/open.html?url=app%3Avalue).
Description wording:
Opens settings.Handles SSO callback routing.Creates a command.
Validation
Before finishing, run:
python3 -m py_compile scripts/extract_deeplinks.py
python3 scripts/extract_deeplinks.py "<App Name>" --format markdown
rg -n "[ \t]+$" README.md contributions.md CONTRIBUTING.md scripts skills
If --scan-bundle --scan-unregistered finds noisy candidates, keep them out of the README and mention them as unverified notes instead.