Skip to content

ARCHITECTURE · 13

The store: one directory, nothing hidden.

Everything tebako keeps on a machine lives under one directory, ~/.tebako. Runtimes download once and are shared by every application; payloads stay byte-identical with what the publisher released; uninstalling means deleting files. There is no daemon, no database, and no state anywhere else.

Note

The store is shipped in v2.0.0; inspect it with tebako info store.

The layout

Precious things (config, trust pins, and keys) sit next to re-derivable things (runtimes, payloads, and registry caches), so a backup policy and a cleanup policy are both obvious. Every downloaded artifact carries its own trust anchor beside it.

~/.tebako — override with TEBAKO_HOME runtimes/ruby-3.3-3.3.7-macos-arm64/ ├── tebako-runtime-…-macos-arm64 0755 ├── tebako-runtime-…-macos-arm64.tfs 0444 · the env image ├── <image>.sha256 ◀ the trust anchor └── <image>.origin — where it came from payloads/metanorma/ ├── 1.2.3.tfs 0444 — byte-identical with the release ├── 1.2.3.tfs.sha256 ◀ verified at install, never per run └── 1.2.3.manifest.yaml — the manifest, mirrored out shims/ ├── metanorma → link to the dispatcher; this dir on PATH └── .disabled.yaml — tools you parked registries/ └── <sha>.yaml (+ .fetched-at) — dispatch cache, 24 h TTL config.yaml your defaults · your registries · runtime preferences keys/  trust/ your signing keys · pinned publisher keys journal.log  locks/  tmp/ THE HOUSE RULES A run is a run. Executing a package never installs its slices. tebako install is the verb. Atomic installs. Downloads land in tmp/ and rename into place — a partial install is invisible, never half-used. One writer at a time. Per-entry file locks, 120 s timeout, a stale lock names itself. Verify once, run forever. The .sha256 sidecar means "verified at install". Runs never re-verify — that is what makes them fast. Read-only artifacts. Payloads and images are 0444. Same name+version with different bytes is refused loudly, never overwritten. Offline is a mode. TEBAKO_OFFLINE=1 — cache hit, or a named error. Never a surprise fetch.

Figure 1 — The ~/.tebako store layout: runtimes, payloads, shims, registries, config, keys, trust, journal, locks, and tmp — with the house rules beside them.

Install and run are different verbs

Double-clicking a package, or executing it in a terminal, runs it: the loader resolves the runtime (downloading it once if needed, which is runtime resolution, shared infrastructure, not installation) and starts the program. Nothing from the package’s payload slots enters the store.

tebako install is the explicit verb: it brings a payload into the store, downloaded to a temporary location, verified against its published SHA-256, and renamed into place read-only, and it registers a shim for every command the payload declares. Registry installs always register shims, and installing a local package file registers them only when the caller passes --shims. tebako uninstall removes the shims and the cache entry.

The store itself is versioned: a single integer marks its layout generation. A newer store refuses an older tool with a named error instead of a silent mix, and an older store is migrated by name, never silently rewritten.

Installs are lazy by default

A runtime install does not wait for the whole env image. The install fetches and pins the image’s block-checksum sidecar, and the image’s 4 MiB block groups arrive on demand — a run touches only the groups it reads — while a background seal completes the entry into the same bytes a whole-image install would have produced. A sealed entry is byte-identical in both modes, which makes the mode a scheduling decision rather than a format. A release that does not serve the lazy wire installs eagerly, with a loud notice, and TEBAKO_RUNTIME_LAZY=0 — or runtime_lazy: false in config.yaml — restores the whole-image install for the machine.

Housekeeping

The cache is available for inspection and pruning. Everything here is read-only against the store, and nothing fetches.

See what is cached
tebako cache list
tebako info store      # disk usage by section
tebako info runtimes   # with --remote: what the factory offers
Reclaim space
tebako cache prune --older-than 90d
tebako cache prune --all

Pruning only ever removes re-derivable artifacts, and the next run that needs one downloads and verifies it again. Config, keys, and trust pins are never pruned.

Why a directory and not a database

The reason is that the store contents are the authority. Every artifact carries its own proof (the sidecar), its own provenance (the origin marker), and its own manifest mirror, so the store is auditable with ordinary tools, repairable by deleting things, and portable by copying it. The registry caches are the only derived state, and they rebuild themselves on a 24-hour cycle or on tebako update-registries.