tinx documentation
tinx is a workspace-first runtime for OCI-distributed provider packages. Instead of installing tools globally, you declare provider packages in a workspace, let tinx lock and cache them, and execute commands through lazy workspace shims.
Use tinx when you want to:
- pin tool packages to a project workspace
- expose multiple commands from one provider package
- lazily materialize OCI-backed binaries and setup-installed tools
- reuse one global provider cache across many workspaces
Core concepts
Workspace
A workspace is the execution boundary. It declares provider aliases and sources, writes a lock file with resolved versions and digests, and rebuilds .workspace/ shell artifacts whenever the declared state changes.
Provider package
A provider package is the distribution unit. Canonically, a provider is a normalized package of resources stored as an OCI artifact.
The active resource kinds are:
- Tool: a command surface with a runtime and optional dependencies
- Bundle: OCI-backed binaries or tarred asset payloads
- Asset: a mounted view of a bundle inside the provider store
- Environment: exported variables and path additions
Legacy manifests that declare runtime: binary, entrypoint, and platforms are still accepted, but tinx normalizes them into the same internal package model.
Tool
A tool is the executable surface tinx resolves at runtime. One tool is usually marked as the provider default, while additional tools contribute command names through provides.
Tools can depend on other tools inside the same provider. That is how setup-style providers work: a bundled installer tool can materialize a second tool only when its shim is used for the first time.
Alias and provided commands
A workspace alias points at the provider default tool. tinx also writes shims for every command in provides, so a single provider can expose several workspace commands.
Runtime plugin
The runtime is internally split into built-in plugins:
oci: materialize a tool from bundle layers in the provider artifactscript: run an install script that creates the tool binary on demandlocal: execute an existing path, including a path created by another tool
Tool execution is still normal process spawning. The plugins only decide how a tool is resolved and installed.
tinx home vs workspace
Two storage layers matter:
| Layer | Purpose |
|---|---|
| tinx home | global cache for providers, OCI store content, and metadata |
| workspace | project-specific runtime state and configuration |
This separation enables global caching, per-project isolation, and reuse across workspaces.
Mental model
Provider package (OCI artifact)
↓
Installed into tinx home
↓
Referenced in a workspace alias
↓
Workspace sync writes .workspace/bin shims
↓
Command enters hidden tinx __shim
↓
Tool plan is resolved and missing tools are installed
↓
Target process executes with the merged environment
That is why a workspace can feel instant after the first install. Metadata and OCI content are cached globally, while actual tool binaries are only materialized when a command needs them.
Why tinx exists
Modern tooling problems usually look like this:
- inconsistent tool versions across machines
- setup scripts that drift over time
- global installs that conflict with each other
- CI environments that behave differently from local shells
tinx addresses those problems by making provider packages declarative, using OCI as a universal distribution format, isolating execution per workspace, and making lazy reproducibility the default.
Design principles
Workspace-first
Execution always happens inside a workspace.
OCI-native
Provider packages are stored and transported as OCI artifacts.
Normalized package model
Legacy shorthands and modern multi-resource manifests end up in one internal package representation.
Lazy materialization
Only materialize bundled binaries or install setup-managed tools when a command actually needs them.
Pluggable runtimes
Tool execution stays normal process execution, but resolution and install behavior comes from built-in runtime plugins such as oci, script, and local.
Deterministic runtime
The same workspace should behave the same way everywhere.
Typical workflow
Declare a workspace:
apiVersion: tinx.io/v1
kind: Workspace
workspace: demo
providers:
node:
source: core/node
Initialize it and run commands:
tinx init ./tinx.yaml
tinx -- node --version
tinx status
tinx ls
The workspace sync prepares .workspace/, writes shims for aliases and provided commands, and records the resolved provider versions. The first command run then materializes only the tools it needs.
What changed in the current architecture
The current runtime is not a single provider binary launcher anymore. It is a normalized package runtime with:
- explicit
Tool,Bundle,Asset, andEnvironmentresources - lazy shims that re-enter tinx through
__shim - a tool dependency planner for setup-style providers
- managed-install tools declared with
install.toolandinstall.path - tool inventory surfaced by
tinx lsandtinx status
What tinx is not
- Not a language-specific package manager
- Not a build system
- Not a container orchestrator
It is a runtime layer for tool packages and workspace execution.
How to read the docs
Start with:
Then read:
Summary
- Workspace defines aliases, locking, and runtime state.
- Provider package defines tools and the resources they need.
- Tool defines what command tinx resolves and how it is installed.
- Runtime plugins materialize or install tools and then execute them.