Multi-Resource Uniform Locator · v0.5.0 · experimental
One identifier that opens a whole working context.
A URL addresses one resource. An mURL addresses a set of them — a repository, its docs, its dashboard, a working directory, a terminal — under a single name that can be inspected before anything happens.
brew install thatwasyahya/murl/murl
6 resources1 consent step0 shells
What an mURL is
A name for a set, with a document in between.
The indirection through a manifest is the whole point. Because the set
is a document rather than a string, it has a canonical byte form — so it
can be hashed, signed, versioned, cached, diffed, and above all
shown to you before it acts. Publishing a namespace means
serving static JSON under /.well-known/murl/: no registry,
no account, no new infrastructure. An mURL is a name, never a container.
This is a proposal with a working implementation, not a standard.
The murl scheme is unregistered, no third party has adopted
it, and the format may still change before 1.0. Read it as a design
worth arguing with — the specification page
says what that means in practice.
What resolution looks like
The plan is printed before anything opens.
Real output from murl resolve against the example destination in the repository. Every leaf is an ordinary URL or path handed to the application you already use; mURL is a composition layer above locators, not a replacement for them.
$ murl resolve murl://local/demo/project-x Project X (murl://local/demo/project-x) Everything that makes up the Project X development context. manifest: local store (~/.local/share/murl/names/demo/project-x.murl.json) trust: LOCAL manifest: local store (~/.local/share/murl/names/demo/team.murl.json) trust: LOCAL resources: ├─ source SAFE https https://github.com/example/project-x ├─ docs SAFE https https://docs.example.com/project-x ├─ issues SAFE https https://jira.example.com/projects/PX ├─ monitoring SAFE https https://grafana.example.com/d/project-x ├─ workspace SENSITIVE dir ~/projects/project-x ⚠ consent: SENSITIVE resource ├─ term DANGEROUS terminal ~/projects/project-x ⚠ consent: DANGEROUS resource ├─ wiki SAFE https https://wiki.example.com/team └─ chat SAFE https https://chat.example.com/#/room/team $
-
resolve
murl resolveprints the fully resolved plan: every resource after nested destinations are spliced in (wikiandchatcome fromteam), its tier, where each manifest came from and whether it is trusted. Nothing opens. -
inspect
The plan is the thing you agree to. Consent to a name would be meaningless — a name can point anywhere — so consent is always to the set, tier by tier, with local paths spelled out.
-
consent
murl openshows the same plan and asks once. Each resource then goes to its handler as an argv array: browser, file manager, terminal app. No target string ever reaches a shell.
Three tiers, decided locally
Classified by what a resource is, never by what a manifest claims.
An identifier that can make an operating system open many things is an attack primitive by default. So the tier derives from kind plus target, the policy lives in local, user-owned configuration, and no manifest content can reach it.
Rendered by a sandboxed browser. Worst case is roughly a tab.
Non-executable local paths. Opening one exposes or touches local data.
Opening it is, or is one dialog away from, code execution. A file that is really a .desktop, .lnk, .sh or .exe lands here too — classification looks at the target, not the label.
That last rule is the keystone. Users can be talked into one click,
and one click is exactly what a hostile mURL gets; making terminals
from unknown senders un-clickable removes the social-engineering path
rather than warning about it. What remains for an attacker is getting
you to run murl trust add or murl name add —
deliberate, documented acts.
The full security model, and what it does not defend against
- SAFE resourceprompt
- SENSITIVE resourceprompt
- DANGEROUS resource, manifest trustedprompt
- DANGEROUS resource, manifest untrusteddeny — not promptable
- Expired or not-yet-valid manifestSAFE prompts · rest denied
- Scripted consent
--yescovers SAFE only
Install
Two binaries; only murl is required.
Installing registers nothing and starts nothing. Making murl:// clickable is a separate, explicit step: murl os install.
cargo install murl-cli
# optional: the resident consent surface
cargo install murl-daemonThe crate is murl-cli; the binary it installs is murl, in ~/.cargo/bin. Needs Rust 1.75 or newer.
brew install thatwasyahya/murl/murlmacOS and Linux, from the thatwasyahya/murl tap.
scoop bucket add murl https://github.com/thatwasyahya/scoop-murl && scoop install murlWindows, from the scoop-murl bucket.
winget install thatwasyahya.murlpending review Submitted to winget-pkgs with all checks green; this command does not work until a maintainer merges it. Use Scoop or cargo on Windows meanwhile.
git clone https://github.com/thatwasyahya/mURL && cd mURL
git checkout v0.5.0
cargo install --path crates/murl-cli
cargo install --path crates/murl-daemon # optional; the consent dialog on macOSFour crates, pure Rust, unsafe_code forbidden workspace-wide. cargo test and bash examples/demo.sh are worth running once before trusting it with anything.
The first five minutes
murl resolve before murl open is the habit worth forming: it prints the fully resolved plan, every tier, and the trust status of the manifest, without dispatching anything.
murl create --name "Project X" # write a starter manifest
murl validate project-x.murl.json
murl name add project-x project-x.murl.json # install as murl://local/project-x
murl resolve murl://local/project-x # see the full plan — nothing opens
murl open murl://local/project-x # consent, then dispatch
murl open 'murl://local/project-x#docs' # just one part of it
murl keygen && murl sign project-x.murl.json # sign it
murl os install # make murl:// clickableRead further
The argument, in full.
- The specificationspec.html Grammar, manifest format, resolution, canonical form and signatures — plus the conformance suite a second implementation can test against.
- The security modelsecurity.html Tiers, consent, trust, the hardening that resolution and dispatch apply — and what none of it defends against.
- Engineering docsgithub.com/…/docs Why this exists, architecture, the threat model and its sixteen threats, the trust model, OS integration, the daemon, stability and roadmap.
- The repositorygithub.com/thatwasyahya/mURL Source, tests, fuzz targets, conformance vectors, and issues.