Shape Packages

Shape Packages

The central registry for Shape packages: a sharded, line-oriented index repository, exactly like Cargo's crates.io-index. Every published version of every package lives in it, immutable, next to the tarballs it describes. The shape toolchain resolves shape add against the index over HTTPS.

The bundled standard library is part of the toolchain and is not a package: HTTP, crypto, JSON and hex serialization, filesystem access, collections, concurrency primitives, and math helpers all ship with std. Use them with import std.

Central registry

The index is served at https://packages.shape-lang.org/index/ from the packages-index antique repository. There is one file per package, sharded cargo-style:

1/<name>/<name>              (1 char)
2/<name>/<name>              (2 chars)
3/<first>/<name>             (3 chars)
<first2>/<next2>/<name>     (4+ chars, e.g. /nu/nu/nui)

Each file is newline-delimited JSON, one line per published version:

{"name":"nui","vers":"0.1.0","deps":[],"cksum":"<sha256 of the tarball>","features":{},"links":null,"v":2}

Fields: name, vers, deps (each dependency with name, version_req, features, default_features, optional), cksum (SHA-256 of the tarball), features (feature → enabled dependency names), links (reserved for native-libs owned by the toolchain), v (schema version, currently 2).

Resolution rules, mirrored in the client:

Install a package

shape add nui
shape fetch

shape add records the dependency in package.toml. shape fetch vendors the declared packages and their transitive dependencies into ~/.shape (override with SHAPE_STORE) and writes shape.lock.

import nui

fn main() -> Int effects io:
    let page = nui.column([nui.heading("island"), nui.button("Follow", "follow")])
    print(nui.render(page))
    0

package.toml

A package is described by package.toml, exactly like Cargo.toml: a metadata section and a dependencies section. Top-level scalar metadata belongs in [metadata]; dependencies map package names to version requirements or tables with from and version.

[metadata]
name = "nui"
version = "0.1.0"
description = "Declarative UI trees for Shape."
repository = "https://code.input.cx/shape/nui"
license = "Proprietary"
authors = ["Input"]

[dependencies]
http = "0.1.0"
store = { from = "antique://code.input.cx/shape/store", version = "0.2.0" }

[dev-dependencies]
shape = "*"

Local modules and the standard library resolve without declarations. A package's own dependencies in package.toml are vendored from the same store roots as everything else — transitively resolved. shape init scaffolds a new package for you.

shape.lock

shape fetch and shape update generate shape.lock next to your package.toml, recording the exact resolved packages (direct and transitive) and a content hash of every file in each package:

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

[[package]]
name = "nui"
version = "0.1.0"
sha256 = "fc951fbb4a77b5446debca22b66b62acdc6c5ee644728a82c15a535085694050"

Publish a package

Any Shape source tree is publishable. Layout convention: name.shape (the package's entry module), optional extra modules, a package.toml, tests runnable with shape test.

shape publish --to antique://code.input.cx/shape/mypackage --message "initial release"

Then add (or append to) the package's file in packages-index — one line per version with the tarball cksum — review and land it with antique review and antique land. The site redeploys the index automatically on landing.

Private packages

There is no god-mode in the index; privacy is a property of the source you name, not a flag on the server.

Browse packages

Filter:

The standard library ships with the toolchain and is not a package: std provides HTTP client, crypto (sha256, hmac), JSON/hex/bytes serialization, filesystem (std.file_read, std.file_write), collections (std.collections), concurrency (std.spawn, std.wait, std.cancel, std.sleep, std.parallel), and math (std.min, std.max, std.parse_int, bit operations). Nothing extra to install beyond import std. The http package is a thin veneer over host HTTP for projects that want a typed client without pulling std networking into their binary.

FAQ

What is in the standard library vs a package?

Anything every application wants with zero dependencies is in std and ships with the toolchain. Reusable libraries, versioned and community-maintained — like nui — are packages, discovered like any crates.io-style package via the index.

Do I have to use the central registry?

No. shape add name --from <source> records exactly that source and never reads the index. Use it for private, experimental, or air-gapped dependencies. The index is the default because it gives exact, hash-verified, reproducible resolution by default.

How are versions chosen?

Exactly the version in package.toml. shape add nui picks latest from the index at add time; the lockfile records what it picked, with hashes.

Is there a lockfile?

Yes, always: shape.lock records direct and transitive versions plus a content hash per package, generated on every shape fetch / shape update. Commit it.

Shape · Playground · Source