Shape Packages

Packages for Shape

Shape's package manager is built into the shape toolchain. It installs packages from source repositories (antique or git) into a shared store, and resolves the exact versions you declare in dependencies.toml. There is no central registry: publish a package anywhere that speaks git or antique, and depend on it with one line.

Install a package

shape add http
shape fetch

shape add records the dependency in dependencies.toml. shape fetch vendors the declared packages, their transitive dependencies, and writes shape.lock. Then import it in source, with no version in sight:

import http

func main() -> Int effects io, network:
    let response = std.http_get("https://example.com/")
    print(response.status)

dependencies.toml

dependencies.toml is the only place that declares external package dependencies. It is the authoritative source for versions, and the compiler refuses an unversioned or undeclared package. Local modules and the standard library resolve without a manifest.

http = "1.0.0"
ui = { from = "git+https://code.input.cx/shape/ui.git", version = "1.0.0" }
state = { from = "antique://code.input.cx/shape/state.git", version = "0.9.0" }

Keys are package names. Values are either a version string, or a table with version and an optional from source. shape init creates an empty dependencies.toml in the current directory.

Commands:

shape.lock

shape fetch and shape update generate shape.lock next to your dependencies.toml. It records the exact resolved packages (direct and transitive) and a content hash of every file in each package, so the same manifest resolves to the same bits on every machine.

# generated by shape fetch; records the exact resolved packages and their hashes

[[package]]
name = "http"
version = "1.0.0"
sha256 = "a3f8…"

Publish a package

Any Shape source tree can be published as a package. Packages are ordinary repositories; version directories are not part of the source layout.

shape publish --to antique://code.input.cx/shape/mypackage --message "initial commit"
shape publish --to git+https://code.input.cx/shape/mypackage --message "initial commit"

Consumers then write a top-level entry in dependencies.toml:

mypackage = "1.0.0"
# or pin a different source repository:
mypackage = { from = "git+https://code.input.cx/shape/mypackage.git", version = "1.0.0" }

Notes:

Browse packages

Filter the list:

The list above is the intended set of official packages. Publishing for each package follows the availability of its source repository; nothing is installable that has not been published yet. Watch code.input.cx/shape for availability.

FAQ

Why no central registry?

Registry infrastructure is a single point of failure and a single point of control. Shape resolves packages directly from repositories, with content hashes in shape.lock. Anyone can mirror any repository; resolution is reproducible either way.

What about global caches?

The shared store lives at ~/.shape (override with SHAPE_STORE). SHAPE_PATH extends module search roots for advanced setups.

How are versions chosen?

Exactly the version in dependencies.toml. There are no ranges, no dist-tags, and no implicit "latest". If you want a different version, change the manifest and run shape fetch.

Shape · Playground · Source