Distribution
MTHDS packages are distributed using a federated model: decentralized storage with centralized discovery. The repository IS the package — no upload step, no proprietary hosting, no service that must be up for an install to succeed.
Storage: Git Repositories
Packages live in Git repositories. Authors retain full control, and publishing is pushing a tag — nothing else. There is no pack or archive artifact and no registry account on the critical path.
A repository can contain one package at its root, or several packages in subdirectories — a library repository. Either way, a specific package is identified by its manifest, never by a directory path (see Locating a Package Inside a Clone).
The Versioned Reference
One reference grammar names a package everywhere — in tooling, in APIs, and in the lock file:
<address>[@<tag>]
- The address is the package's manifest
address(see The Manifest): hostname/path, e.g.github.com/acme/legal-toolsorgithub.com/mthds/methods/documents. It is simultaneously the package's identity and its fetch location. - A bare address refers to the repository's default branch at its current HEAD.
@<tag>refers to the repository at that Git tag. The recommended tag form isvX.Y.Z(e.g.github.com/acme/legal-tools@v1.2.0) — the same pinning gesture the lock file formalizes.
Clone URL Derivation
The first two path segments after the hostname name the repository; the clone URL is derived from them:
github.com/acme/legal-tools → https://github.com/acme/legal-tools.git
github.com/mthds/methods/documents → https://github.com/mthds/methods.git
- Take the hostname and the first two path segments.
- Prepend
https://. - Append
.git.
Any path segments after the first two are not part of the clone URL — they select a package within the clone.
Open question: hosts with nested repository namespaces
The two-segment rule matches hosts whose repositories live at <host>/<owner>/<repo> — the layout of every address in this specification. On hosts that allow nested repository namespaces (such as GitLab subgroups), the repository/package boundary inside an address is ambiguous under this rule; how such addresses are partitioned is an open question of the standard, deliberately recorded rather than silently decided. Until it is settled, portable package addresses SHOULD use a <host>/<owner>/<repo> repository.
Locating a Package Inside a Clone
A package is located inside a clone by manifest identity, not by directory path. Directory names carry no meaning: a compliant tool scans the clone for METHODS.toml files and selects the package whose identity matches the requested address:
- a repository-root package matches when its manifest
addressequals the requested address; - a package in a library repository matches when its manifest
address + "/" + nameequals the requested address. For example, a manifest withaddress = "github.com/mthds/methods"andname = "documents"is the packagegithub.com/mthds/methods/documents, wherever it sits in the repository tree.
If no manifest matches, or more than one does, the tool MUST fail loudly, listing the package identities the clone does contain. It MUST NOT fall back to guessing by directory name.
Version Tags
Version tags in remote repositories may use a v prefix (e.g., v1.0.0). The prefix is stripped during version parsing. Both v1.0.0 and 1.0.0 are recognized.
Tags are listed using git ls-remote --tags, and only those that parse as valid semantic versions are considered. Fetching a resolved version clones at its tag: git clone --depth 1 --branch {tag}.
Open question: version tags in a library repository
Git tags are repository-wide, while each package in a library repository carries its own manifest version. How repository tags map to per-package versions — per-package tag prefixes are the anticipated direction — is an open question of the standard, deliberately recorded rather than silently decided. Until it is settled, packages that need independently versioned releases SHOULD live in their own repositories, and a library repository SHOULD version its packages in lockstep.
A tag can be re-pointed; the commit it resolved to cannot. Tools therefore record the resolved commit SHA of every fetch — it is the provenance entry in the lock file and the honest key for any clone cache. Every fetched-package operation SHOULD be attributable to its (address, tag, commit) triple.
The Two Caches
Two caches with two distinct jobs stand between a remote repository and a running method:
- The global VCS cache,
~/.mthds/packages/{address}/{version}/, holds fetched package sources, shared across projects. Entries are written atomically (staging directory, then rename), the.gitdirectory is removed, and each entry records the commit SHA it was fetched at. - The project-local method cache,
.mthds/methods/<name>/inside the consuming project, is what closure assembly reads. It is deterministic by construction: resolution reads only from disk.
Install is the bridge. Installing a package's dependencies walks the lock file, fetches anything missing into the global cache (verifying the byte hash against the lock — a mismatch is a hard failure), and materializes each locked dependency into the project-local cache. After install, resolving and running the method touches no network.
Fetched Content and Runtime Policy
A fetched package directory may contain files beyond .mthds bundles — documentation, assets, or implementation-specific code. What a runtime executes from fetched content is runtime policy, not standard semantics: a runtime MAY refuse fetched executable content, or classes of it, according to its own security model, and SHOULD say so with an error that names the rule rather than silently ignoring files. The standard requires only that the MTHDS content itself — manifest, bundles, lock — be interpreted as specified.
Discovery: Registry Indexes
One or more registries index packages without owning them: they crawl known package addresses, parse manifests and bundles, and serve search, package pages, validation badges, and freshness signals.
The registry is off the install path — by design, not by accident. Because version resolution needs nothing beyond the manifests and the repositories' own tags, and packages are fetched straight from their repositories, bare Git access is sufficient to resolve, lock, and install anything. A registry can disappear without breaking a single build.
Multi-Tier Deployment
MTHDS supports multiple deployment tiers, from local to community-wide:
| Tier | Scope | Typical use |
|---|---|---|
| Local | Single .mthds file, no manifest |
Learning, prototyping, one-off methods |
| Project | Package in a project repo | Team methods, versioned with the codebase |
| Organization | Private Git hosting + an internal registry index | Company-wide approved methods, governance |
| Community | Public Git repos + public registries | The open method ecosystem |
Registry proxy and mirror modes — an organization-tier convenience layer over this model — are a future direction; they are additive precisely because the install path never depended on a registry.
See Also
- The Registry — the discovery surface that indexes packages.
- The Lock File — how fetched versions are pinned and verified.
- Version Resolution — how versions are selected.
- Specification: Library Crate Format — the resolution artifact assembled from the project-local cache.
- Specification: Fetching Remote Dependencies — normative reference for the fetch algorithm.
- Specification: Cache Layout — normative reference for cache paths.