Grasm v1.0.0 Get started

Reference

Packages

A manifest, a resolver, a lockfile — and a ceiling on what a dependency may do, checked at compile time in every consumer.

A manifest

[package]
name = "ecommerce_cart"
version = "1.0.0"
entry = "main.gr"
capabilities = ["io", "net"]

[dependencies.json]
path = "../../packages/json"
version = "^1.0.0"

The ceiling

capabilities is the set of effects this package may perform. Effects are inferred from source, so the claim is checked rather than trusted. A dependency that starts reading files without declaring io fails to build — and it fails in your build, not silently in theirs.

This is the part of the package system worth having. Version resolution is plumbing every language has; a supply chain where a dependency's reach is a compile-time fact is not.

Commands

grasm deps            # resolve, check ceilings, write grasm.lock
grasm deps --locked   # fail rather than update the lockfile

What ships today

660 libraries, all written inside this repository because there is no registry to get one from. The table below is a sample of them — the ones where the capability column says something worth reading.

PackageCapabilitiesWhat it is
httpnoneRequests, responses, routing with :param and * segments, percent decoding, HTML escaping.
http_serverio, netThe accept loop, and many conversations on one thread. Depends on http.
http_clientnetDials, sends what http composed, reads until the declared frame arrives. Depends on http.
jsonnoneParse, render, reach into a document, build one. Six programs in ProjectGold/ depend on it.
bytes_codecnoneHex, base64, url-safe, constant-time compare.
timenoneCivil calendar, ISO-8601, durations. The clock is a parameter.
randomnoneSeeded generator, uniform without modulo bias, shuffle.
uuidnonev4 and v7. The entropy is a parameter.
pathnoneJoin, normalise, split, containment. Touches no disk.
urlnoneParse, build, resolve, percent code, query strings.
logio, LogLogging as an effect: a library that logs declares Log, not io.
csvnoneQuoting, embedded newlines, headers, any separator.
clinoneFlags, bundles, subcommands, --, a generated help page.
testingnoneCases as values, table-driven suites, a golden diff that names the line and column.
tomlnoneTables, arrays, inline tables, reached by dotted path.
resiliencenoneBackoff with full jitter, circuit breaker, token bucket, deadlines — the clock is a parameter.
cachenoneCache[V], least-recently-used with an expiry.
crypto_hashnoneSHA-256, HMAC-SHA-256, PBKDF2, constant-time compare — every digest checked against FIPS 180-4, RFC 4231 and RFC 6070.
regexnoneA Thompson machine, so matching is linear in the input for every pattern — (a+)+b against thirty as returns at once.
fsioWalk, glob, copy, temporary paths. The arithmetic half is path, which declares nothing.
jwtnoneHS256. The algorithm comes from the caller, never the token — so alg: none is refused because it disagrees, not by a special case.
corsnoneA request in, the headers a response needs out.
dotenvio.env files. It answers a map and never touches the process environment.
sanitizenoneEscaping by destination — HTML text, an attribute, a script block, a URL, a shell argument, a header. There is no general escape, because there is no such thing.
metricsMetricCounters, gauges, histograms and the Prometheus text format — the registry is an effect, so a library that counts declares Metric and not io.
errorsnoneA failure carrying its cause, its place and its fields. Grasm has no captured backtrace, so every link is one somebody wrote — which is the work, and is why nothing is lost.
traceTraceSpans and W3C traceparent, as an effect. An all-zero trace id is refused, since a receiver that accepts one joins every unrelated request into a single trace.
redisnetRESP2 and RESP3 both — a client that reads only one refuses half the servers it meets. The encoder and decoder are pure, so the demo drives them with bytes and never opens a socket.
websocketnoneThe upgrade handshake (checked against RFC 6455's own example) and the frame format. A frame's masking is checked in both directions, because a server that accepts an unmasked one sits behind a proxy that can be poisoned. ws:// only — there is no TLS.
passwordnonePBKDF2-HMAC-SHA256. The stored form carries its own algorithm and cost, so a file written today can be verified after both change.
protobufnoneThe wire format: varints, zigzag, packed and nested fields. A message without its schema still reads, which is what makes a proxy possible. Not gRPC — that needs HTTP/2 and TLS.
postgresnetThe v3 wire protocol and SCRAM-SHA-256, checked against RFC 7677's own vector. No TLS, so a trusted network or a local socket.
xmlnoneParse and render. No DTD and no external entities, ever — that is what XXE is, and a first release does not need it. Which is also why this can declare nothing and mean it.
oauth2noneThe authorisation-code flow with PKCE (checked against RFC 7636's vector) and client credentials. PKCE and state are not optional here.

563 of the 660 libraries declare nothing. Only 97 ask for any capability at all. That is the pattern the whole design is for, and the number is counted from the manifests rather than asserted: reach is split from computation, so a program that joins paths, formats a date or builds a URL acquires no capability by doing so — and where a library really does need the world, it asks for it as an effect the consumer supplies, which is what log demonstrates.

They are three packages because http cannot open a socket, and that is checked rather than claimed: its manifest declares no capability, effects are inferred from its source, and a version of it that started dialling out would fail to build in every consumer. So a program can parse and route HTTP while remaining provably unable to reach the network, and a program that only builds requests never acquires the ability to send them. In every other language, depending on the HTTP library means depending on something that can.

Where packages come from

The registry is called Blade. It is not a separate program — grasm add pulls from it, grasm publish pushes to it, and grasm deps resolves against it, all from the one binary.

Two sources work today: a path dependency, and a local Blade registry under .grasm/registry (or wherever GRASM_REGISTRY points). Both resolve, lock and check ceilings.

There is no remote registry. Nothing fetches, publishes or verifies over a network yet, and there are no third-party packages to fetch. Both are on the roadmap, and they are the largest thing standing between this language and ordinary use.