Registry and dependencies
A bino registry hosts reusable predef packages — layouts, styles, rule sets and
the resources they need, published under scoped names like @acme/base-layout.
A package is a small file tree, so one package can ship a page, the components
it embeds, a style and a dataset together.
This guide covers declaring dependencies, the lockfile workflow, reproducible installs in CI, and authentication. To author and publish a package of your own, see Publishing packages.
The full command reference lives at bino registry.
The moving parts
Section titled “The moving parts”| File / directory | Role | In git? |
|---|---|---|
bino.toml [dependencies] | What you depend on (name → version or tag) | yes |
bino.lock | Exact resolved versions and digests | yes — commit it |
.bino/registry/ | Materialized package files, one directory per package | no — gitignore it |
The build, preview, serve, and LSP all include .bino/registry/ in the
manifest set automatically, so installed packages behave like local documents.
A package whose name collides with a local document of the same kind fails the
build's duplicate-name validation; rename the local document.
Declaring dependencies
Section titled “Declaring dependencies”Dependencies live in bino.toml:
[dependencies]
"@acme/quarterly-report" = "1.2.3" # exact version = pinned
"@acme/base-layout" = "latest" # a tag name = follows the tagPackage names are always @scope/name. Values are either an exact version
(1.2.3 — held until you change it) or a tag (latest, stable, ... —
moves when you run bino registry update). There are no version ranges.
You rarely edit this table by hand — bino registry add and
bino registry remove maintain it:
bino registry add @acme/base-layout # follows "latest"
bino registry add @acme/quarterly-report@1.2.3 # pins the version
bino registry remove @acme/base-layoutadd resolves the transitive closure (exactly one version per package — a
conflicting pin fails with a dependency-conflict error), downloads every file
of every package, verifies each file's digest, and only then writes anything.
A package's files land verbatim under .bino/registry/<scope>/<name>/, keeping
the layout and the comments its author wrote:
.bino/registry/
└── acme/
└── finance-kit/
├── finance-kit.yaml # the package's main document
├── components/waterfall.yaml
└── resources/logo.pngA package published as a single document occupies the same shape with one
file, <name>.yml. Everything is then pinned in bino.lock.
Installed packages keep their scoped name as metadata.name, which is why
@scope/name is a valid document name — see
Name scoping.
The lockfile workflow
Section titled “The lockfile workflow”bino.lock records the exact version, digest, kinds, file list and dependency
edges of every installed package. Commit it: it is what makes a checkout
reproducible.
The digest of a package is taken over its file manifest, and each file has its own digest: manifests over their canonical form, so reformatting or re-commenting a document does not change its identity, and resources over their raw bytes.
bino registry install– re-creates.bino/registry/exactly as pinned, without re-resolving. Use it after a fresh clone and in CI. It refuses to run when the lockfile drifted from[dependencies](or is missing) and points you toupdate.bino registry update– re-resolves tag-following entries to their newest versions and rewrites the lockfile; exact pins are held. Pass package names to update selectively.bino registry verify– re-hashes every installed file against the locked digests. Digests cover the canonical document form, so reformatting a manifest does not fail verification — content changes do. A file inside a package directory thatbino.lockdoes not record is reported too, since the build would otherwise load it.
A typical CI job:
bino registry install # reproduce the locked state
bino registry verify # fail on any tampered/modified package
bino buildReferencing installed components
Section titled “Referencing installed components”Component packages (Text, Table, ChartStructure, ChartTime, Tree, Grid,
LayoutCard, Image) are consumed with ref on a layout child, grid child, or
tree node — the scoped package name is the document name:
apiVersion: bino.bi/v1alpha1
kind: LayoutPage
metadata:
name: commentary-page
spec:
children:
- kind: Text
ref: "@thatscalaguy/test"
params:
REGION: testparams passes values into the referenced document, exactly like
LayoutPage params: the package declares its
parameters in metadata.params and uses ${NAME} placeholders in its spec:
apiVersion: bino.bi/v1alpha1
kind: Text
metadata:
name: "@thatscalaguy/test"
params:
- name: REGION
type: string
default: EU
spec:
value: "Report for ${REGION}"Precedence is the same as for pages: explicit params beat declared defaults,
which beat an environment variable of the same name. select params expose a
${NAME_LABEL} companion. Param values must be quoted strings (YEAR: "2024").
Inline spec fields on the child still act as overrides and are merged after
the params are expanded. Only ${NAME} placeholders for parameters declared in
metadata.params are preserved for expansion — any other ${VAR} in a package
is resolved from the environment at load time.
Configuring the registry
Section titled “Configuring the registry”The registry URL is resolved in this order:
- The
--registryflag (auth commands only). bino.toml[registry].url— the per-project setting, committed with the project.- The
BINO_REGISTRY_URLenvironment variable. ~/.bino/config.toml[registry].url— the per-user (global) setting.- The public registry,
https://registry.bino.bi.
Per project, in bino.toml:
[registry]
url = "https://registry.bino.bi" # optional; this is the default
token = "${ACME_REGISTRY_TOKEN}" # optional; literal or ${ENV_VAR}To point every project on a machine at a private registry, use the global config instead:
# ~/.bino/config.toml
[registry]
url = "https://registry.corp.example.com"A project's bino.toml always wins over the environment variable and the
global config. The global config holds only the URL — tokens live in
~/.bino/credentials.json (via bino registry login) or
BINO_REGISTRY_TOKEN. A malformed ~/.bino/config.toml is an error, not
silently ignored. Like credentials.json, it is spared by
bino cache clean --global.
Authentication
Section titled “Authentication”Anonymous access works for public packages. For private registries or
publishing-related workflows, create a personal access token (prefixed
bino_pat_) in the registry web UI (Settings → Tokens), then authenticate
once:
bino registry loginThis validates the token and stores it in ~/.bino/credentials.json (mode
0600, keyed by registry URL; spared by bino cache clean --global). Tokens
are exchanged for a short-lived session token per invocation.
The token used for a request is resolved in this order:
bino.toml[registry].token— a${ENV_VAR}value is expanded from the environment; an unset variable is an error.- The
BINO_REGISTRY_TOKENenvironment variable. - The credential stored by
bino registry loginfor that URL. - Anonymous.
For CI, create a dedicated token in the web UI and pass it via the environment:
export BINO_REGISTRY_TOKEN="bino_pat_..."
bino registry installTokens are listed and revoked in the web UI; bino registry logout removes
and revokes the stored credential.
Publishing
Section titled “Publishing”Packages are published from source with bino publish, from a project whose
bino.toml carries a [package] table:
bino publish --dry-run # validate against the registry, mint nothing
bino publish --bump minorThe registry mints the version from the bump and validates the package before it accepts it. Publishing packages covers authoring a package project end to end.