Examples

Simple block

Minimal block with multi-source resolution, one served port, and a supervised command.

# stackie.redis.yml
stackie.redis:
  sources:
    brew:
      name: redis
      version: latest
    scoop:
      name: redis
      version: latest

  serves:
    PORT:
      port: 6379
      type: db

  command:
    - "redis-server"
    - "--port"
    - "${serves.PORT}"
Referenced schema occurrences
  • Source resolution entrystackie.redis.sources.brew
    SourceDefinitionoptionalmanymap value

    Each sources map value describes one install source candidate for source resolution.

  • Served Redis portstackie.redis.serves.PORT
    PortConfigoptionalmanymap value

    The serves map value declares the port made available to stacks.

Block YAML Format

Reference for Stackie block YAML files generated from the typed Rust block contract. YAML is the serialization format; the public API contract is the typed model plus validation semantics.

Contract Metadata

Breaking changes to typed fields, defaults, serialized names, enum variants, or validation semantics require a new block spec version or an explicit compatibility rule.

Spec version
stackie.block.v1
Typed contract
stackie::block::models::Block
Owning crate
stackie
YAML serialization
Block YAML files serialize into Block. The current block YAML projection follows the block spec version until a separate serialized version field is introduced.
YAML version field
none
Default YAML version
v1
JSON Schema projection
Machine-readable type-shape and editor-assistance projection derived from the typed block model.
Validation rules
1 generated rule
Generated by
stackie gen-yaml-docs

Top-Level Shape

A block file contains one stackie.* top-level key. That key becomes Block.name.

YAML keystackie.<block-name>
Value typeBlock

Block Fields

A block defines how a single service is installed, configured, and run on each platform.

Blocks published to the stackie. namespace (e.g., stackie.postgres) are managed through the Stackie ingredient registry and Cache CDN — they install in seconds with no source compilation. First-party blocks (any name not starting with stackie. or gateway.) describe services you own and run from a local path:. Gateway blocks (gateway.) proxy cloud provider APIs into your local stack.

#tool
boolean|nulloptional

If true, this is a dependency-only block (no command block) Cannot be added directly to recipes, only via depends_on

#category
BlockCategory|nulloptional

Functional category used by catalogs, topology designers, and generated forms.

#command
CommandSpec|nulloptional

Command to execute (supports variable interpolation) Can be: array of strings, single string, or object with posix/windows scripts Example: ["postgres", "-D", "${paths.DATA_DIR}", "-p", "${ports.PORT}"] Example: { "posix": "#!/bin/sh\nmkdir -p /tmp", "windows": "mkdir C:\\tmp" }

#working_dir
string|nulloptional

Optional working directory for the runtime process.

Supports the same interpolation variables as commands and health checks. Stack-level overrides may replace this value for test or compose-specific layouts without changing the catalog block definition.

#vars
object|nulloptional

String variables (accessed as ${vars.NAME}) Example: { "USER": "postgres", "DB": "postgres" }

#var_constraints
object|nulloptional

Allowed values for specific vars.

Maps var names to their permitted string values. When a user overrides a var listed here, only values from the allowed set are accepted. Validated via Block::validate_var_override. An empty string "" is a valid value.

var_constraints:
  GPU_VARIANT:
    - ""
    - "-rocm"
#serves
object|nulloptional

Named port configurations (accessed as ${serves.NAME} or legacy ${ports.NAME}) Example: { "PORT": { "port": 5432, "type": "db" }, "ADMIN_PORT": { "port": 5433, "type": "db" } }

#paths
object|nulloptional

Named filesystem paths (accessed as ${paths.NAME}) Example: { "DATA_DIR": "/var/lib/postgresql/data", "CONFIG": "/etc/postgresql" }

#init
array<BlockInitOperation>|array<CommandSpec>optional

Initialization operations or commands (run once on first start).

Supports two formats:

New declarative format (preferred): Cross-platform operations executed natively in Rust. F0

Legacy format (deprecated, for backward compatibility): Platform-specific shell commands. F1

#allowed_env
array|nulloptional

Environment variables allowed for ${env()} interpolation.

In addition to built-in safe variables (PATH, HOME, JAVA_HOME, etc.), blocks can declare additional environment variables they need access to. This provides a whitelist mechanism for environment variable access in declarative operations.

allowed_env:
  - CUSTOM_CONFIG_PATH
  - MY_API_KEY

Only variables in the built-in safe list OR declared here can be accessed via ${env(VAR_NAME)} interpolation. This prevents accidental leakage of sensitive environment variables.

#environment
object|nulloptional

Environment variables (supports variable interpolation in values) Example: { "POSTGRES_USER": "${vars.USER}", "POSTGRES_DB": "${vars.DB}" }

#sources
object|nulloptional

Package sources for multi-source support (dependency tree system) Maps source names (e.g., "brew", "npm") to package definitions Example: { "brew": { "name": "postgresql", "version": "latest" } }

#tools
array|nulloptional

Runtime tool requirements for this block.

Declares tools that must be installed before this block can run. Stackie will automatically install these tools if they're not present.

tools:
  - java: "21"      # Requires Java 21 (Temurin)
  - go              # Requires any Go version
  - python: "3.11"  # Requires Python 3.11
#depends_on
array|nulloptional

Block dependencies (loaded before this block) Example: ["stackie.config-loader", "stackie.redis"]

#platforms
PlatformSupport|nulloptional

Platform support flags

#health_check
object|object|object|objectoptional

Health check configuration for monitoring block availability Example: { "type": "tcp", "port": 5432, "interval": 30 }

#allow
AllowBlock|nulloptional

Additional sandbox permissions (use sparingly) Defines non-standard filesystem permissions required by this block. Only use for exceptional cases where block needs access beyond default sandbox policy. Example: { "mode": "merge", "permissions": [{ "path": "/bin", "mode": "rx" }] }

#mocker
MockerConfig|nulloptional

Mocker configuration for Docker Engine API compatibility. Maps Docker image names to this Stackie block, enabling docker CLI drop-in replacement. Example: { "images": ["postgres", "library/postgres"], "version_regex": "^(\\d+\\.\\d+)" }

#runtime
boolean|nulloptional

Marks this block as a language runtime that can host user code.

When true, the user-code detector treats this block as a candidate for Pattern A (bind-mount + command) and Pattern B (Dockerfile FROM) translation. Runtime blocks must set mocker.code_mount to indicate the expected mount path.

Not a security boundary — the sandbox decision is made by the caller.

Example: true for Node.js, Python, Go SDK blocks.

#emoji
string|nulloptional

Optional emoji icon for CLI display. Should be a single unicode emoji character that represents this block. Example: "🐘" for PostgreSQL, "🔴" for Redis, "🐬" for MySQL

#default_hooks
object|nulloptional

Default lifecycle hooks for all instances of this block

These hooks run automatically at lifecycle points unless overridden. Stack-level hooks can extend or replace these defaults.

#consumes
map<string, ConsumesEntry>optional

Default consumes declarations: services this block needs at runtime.

Declares the types of services this block requires when used in a managed stack. The pipeline integration reads these and auto-wires the connections using type-based matching. Stack-level consumes: overrides take precedence.

consumes:
  db:
    port_type: db   # needs any block that serves a db port
#tool_env
object|nulloptional

Environment variables to set when this tool is active.

Keys are environment variable names (e.g., JAVA_HOME, GOROOT). Values support ${install_path} interpolation and can be platform-conditional for cases like macOS Java which needs Contents/Home appended to the install path.

Only meaningful on tool: true blocks.

tool_env:
  JAVA_HOME:
    linux: "${install_path}"
    macos: "${install_path}/Contents/Home"
    windows: "${install_path}"
    PATH: "${install_path}/bin"
  • PlatformOrString for the type used as values
#tool_license
ToolLicenseInfo|nulloptional

License metadata for pre-flight acceptance prompts.

When set, stackie will prompt the user to accept the license before installing this tool. Only meaningful on tool: true blocks.

  • ToolLicenseInfo for the type definition
#block_license
ToolLicenseInfo|nulloptional

License metadata for the block's own package, surfaced in the stackie up pre-flight prompt.

tool_license is for SDKs / runtimes installed by tool: true blocks (Node, Python, Temurin, …). block_license is the analogous field for service blocks (PostgreSQL, Traefik, Supabase Studio, …). Splitting them keeps the semantics unambiguous when a service block also depends on a tool block.

Optional — when omitted, the block contributes no row to the service-block section of the license prompt. Populate it for any block whose primary distribution carries a license that the user should explicitly accept.

#versions
array<BlockVersionEntry>required

Supported logical versions for this block.

Every loadable block must provide a non-empty catalogue. Aliases must be unique, and one entry must use the exact alias latest. These semantic rules are enforced by the shared build/runtime semantic validator in crate::block::version_contract in addition to the generated schema's structural checks. A built-in block cannot reach AOT code generation without passing the same version gate used for filesystem-loaded blocks.

Entries provide short selectors for discovery and version-aware commands. This is block-level metadata: it applies to tools, services, databases, applications, and built-in compatibility blocks alike.

The latest alias is the canonical block default. An omitted sources.<provider>.version inherits it; an explicit source version is reserved for a genuinely provider-specific selector. Source definitions are shared across versions, so a block does not repeat its source name or URL for every entry.

The legacy YAML key tool_versions is normalized by the filesystem loader for compatibility, but versions is the only generated and serialized form. Declaring both keys is rejected as ambiguous.

  • BlockVersionEntry for the entry type
#tool_dir_name
string|nulloptional

On-disk directory name under ~/.stackie/tools/ for backward compatibility.

Defaults to the block name suffix when not set (e.g., java.sdkjava.sdk). Set this to preserve existing tool installations when a block is renamed or to match a legacy naming convention.

For example: the java.sdk block sets this to "temurin" so that existing Temurin installations at ~/.stackie/tools/temurin/ are preserved.

Only meaningful on tool: true blocks.

#requires_jna
booleanoptional

Whether this block requires JNA (Java Native Access) extraction during install.

When true, the archive installer will extract any embedded JNA native libraries from the downloaded archive into the appropriate location for the JVM to discover at runtime. Set this on blocks whose runtime ships a bundled JNA dependency that must live alongside the tool's binaries (historically only the Temurin JDK block, but now generalized as a flag).

Defaults to false. Existing block YAMLs without this field continue to deserialize cleanly.

This field is a pragmatic intermediate step. The long-term direction is a generic post_install_hooks system (see SOLID/DRY audit finding 12) that lets blocks declare arbitrary post-install behavior without adding new bool flags to the schema. Once post_install_hooks lands, requires_jna will be deprecated in favor of an explicit hook entry.

#supercache_only
booleanoptional

Whether this block can only be installed from the Cache CDN.

When true, stackie will not attempt a native package-manager install if the Cache CDN reports a miss or is unreachable. Instead it emits crate::sources::resolver::StackOutcome::SupercacheUnavailable and surfaces a clear error to the user.

Set this on blocks whose upstream package name does not exist in any public registry — for example, pre-built artifacts distributed exclusively via Stackie Cache (e.g. supabase-auth, supabase-storage, supabase-realtime, supabase-studio).

supercache_only: true
sources:
  go:
    name: auth
    version: "v2.189.0"
  • crate::sources::resolver::StackOutcome::SupercacheUnavailable

Validation Rules

block.definition· Block

Block definition validation

Validate invariants for a parsed block definition.

This rule enforces the Stackie block namespace, requires at least one package source for registry-backed blocks, and validates any custom sandbox permission declarations.

Nested Types

#AllowBlock

Sandbox permission block with merge/replace semantics

Defines additional sandbox permissions required by an block. Can be merged with default permissions or replace them entirely.

#mode
stringoptional

How to combine with default/stack permissions ("merge" or "replace") Default: "merge"

#permissions
array<SandboxPermission>required

List of filesystem paths with permission modes

#windows_process_ipc
booleanoptional

Enable Windows sibling-process IPC compatibility for this block.

This is a Windows-only sandbox relaxation for native service families that create child processes which must signal each other through creator-owned kernel objects such as named pipes. It keeps the user's SID enabled in the Lockbox restricted token for this block's process family. Use sparingly and only for blocks that require this behavior.

#ArchUrls

Architecture-specific URL mapping

Maps CPU architectures to download URLs. Use when a package has different binaries for different architectures.

#amd64
string|nulloptional

URL for x86_64/amd64 architecture

#arm64
string|nulloptional

URL for aarch64/arm64 architecture

#BlockCategory

Categories describe the role a block plays in a stack so catalogs, topology designers, generated forms, and search filters can group blocks by user intent rather than low-level port details. Use the closest stable role; block definitions that omit the property use the generic BlockCategory::Service default rather than being classified from their names or port details.

ValueDescription
"application"

User-facing or internal application service.

"database"

Relational or general database service.

"document-store"

Document-oriented data store.

"cache"

Key-value cache or in-memory data service.

"queue"

Message queue, event stream, or broker.

"secret-store"

Secret storage or key management service.

"search"

Search index or vector search service.

"object-store"

Object/blob/file storage service.

"web"

HTTP edge, proxy, or web-serving component.

"observability"

Observability, metrics, tracing, or logging component.

"runtime"

Runtime environment for user code.

"tool"

Dependency-only tool block.

"infrastructure"

Infrastructure support service.

"service"

Fallback for services that do not fit another role.

#BlockInitOperation

Cross-platform declarative initialization operation in the runtime's custom-Serde representation.

Accepted shapes

Ensure a directory exists

required: ensure_dir

Copy a file

required: copy

Copy a directory recursively

required: copy_dir

Link a directory into the sandbox

required: link_dir

Write content to a file

required: write_file

Append content to a file

required: append_file

Replace text in a file

required: replace_in_file

Remove a file, directory, or matched path

required: remove

required: run

required: exec

Conditionally execute nested operations

required: if

#BlockVersionEntry

A supported version entry for a block.

Provides both a short alias for user input and the canonical upstream or package version used by version-aware consumers. Tool commands use the same catalogue as service, database, application, and compatibility blocks. Aliases are case-sensitive, must be non-empty and unique within their block, and reserve the exact value latest for the canonical default.

versions:
  - alias: "21"
  version: "21.0.4"
  - alias: "17"
  version: "17.0.12"
  • ToolLicenseInfo for license metadata - Block::versions for the field on the Block struct
#alias
stringrequired

Short alias accepted by version-aware block consumers (e.g., "21", "3.12").

#version
string|objectrequired

Full version string used in download URLs, or platform-conditional version map.

Plain strings work as before. Use a platform map when a version is unavailable on a specific OS (e.g., Erlang OTP 28 has no macOS Intel builds):

- alias: "28"
version:
  linux: "28.0.0"
  macos: "27.2.4"
  windows: "28.0.0"

#CommandSpec

Command specification for blocks

Supports three formats: 1. Simple array: cross-platform binary command with arguments 2. Single string: cross-platform single command 3. Platform-specific: object with posix and windows shell scripts

#ConsumesEntry

Describes how a block consumes a port served by another block in the stack. Appears in the consumes: map of a block node under a logical name (e.g., DB). The interpolation engine resolves ${consumes.DB} to the actual port number.

String shorthand — the value is used as the block name:

consumes:
  db: neon                     # ${consumes.db.PORT}
  storage: stackie.minio       # ${consumes.storage.API}

Typed struct — provides additional filtering options:

consumes:
  db: { port_type: db }              # match any block with a db-type port
  store: { block_override: stackie.minio }  # explicit block reference
#port_type
string|nulloptional

Filters the consumed port by type (e.g., "db", "web"). When set, only ports matching this type are considered. When omitted, any port from the matched block is accepted.

#block_override
string|nulloptional

Explicitly names the block that provides this port, bypassing automatic resolution. Also set automatically when the string shorthand form is used (e.g., db: neon sets block_override to "neon").

If both block_override and port_type are set, block_override selects the block and port_type filters which port within it is used.

#Ecosystem

ValueDescription
"go"

Go compiled binaries (always platform-specific)

"node"

Node.js packages (Next.js standalone builds, etc.) May be universal or platform-specific depending on native dependencies

"system"

System binaries (Homebrew or OS-managed tools compiled for the target platform)

"elixir"

Elixir/Erlang packages

"rust"

Rust packages (crates)

"python"

Python packages (pip/pypi)

"java"

Java/JVM packages

"bespoke"

Bespoke/custom packages that don't fit other categories

#GitHubReleaseArchiveShape

Archive layout declared by a github-releases source.

ValueDescription
"universal"

One release asset is shared by all supported platforms.

"platform_arch"

Release assets differ by platform, architecture, or both.

#HealthCheck

Used in full exampleCommand health check

Health probe in the flattened custom-Serde form consumed by Stackie.

Accepted shapes

required: command, type

required: type, url

required: port, type

required: process_name, type

#HookAction

Action executed for each content match yielded by a for_each_match hook.

Actions intentionally omit source configuration: the parent hook owns file discovery, and each action receives the matched file as its input.

#handler
stringrequired

Handler type to run against the matched content.

#binary
string|nulloptional

Binary path for matched run actions.

Like top-level run hooks, this supports lifecycle interpolation and can reference ${vars.MATCH_PATH} to receive the matched local file.

#args
array<string>optional

Command-line arguments for matched run actions.

#working_dir
string|nulloptional

Optional working directory for matched run actions.

#render_shell_echo_env
booleanoptional

Render POSIX shell echo environment substitutions before this action runs.

Source-image entrypoint files sometimes use constructs such as ` echo "$POSTGRES_USER" inside data files that are later consumed by another binary. Enabling this option materializes a matched-file copy with those shell echo substitutions resolved through the hook environment, then points ${vars.MATCH_PATH}` at the rendered copy for this action.

#vars
map<string, string>optional

Variable overrides applied while this action runs.

These values are merged into the handler context for the action only. They are useful when one glob expansion must feed the same primitive through different connection identities or handler settings.

#continue_on_error
booleanoptional

Continue executing actions or matches if this action fails.

#timeout_secs
integer|nulloptional

Timeout for this action in seconds.

#HookDefinition

Runs a handler (sql, shell, write_file, for_each_match, or run) against files fetched from a source (git, web, or local), inline content, or a declared binary after block initialisation completes.

after_init:
  - handler: sql
  source:
    type: git
    url: "https://github.com/supabase/postgres"
    reference: "v15.1.0.117"
    files:
      - "migrations/db/init-scripts/*.sql"
      order: 1
      timeout_secs: 120
#handler
stringrequired

Handler type: "sql", "shell", "write_file", "for_each_match", or "run"

#source
stringoptional

Source type: "git", "web", or "local" Optional for write_file handler which uses path/content instead

#source_config
SourceConfigoptional

Source configuration Optional for write_file handler which uses path/content instead

#files
HookFilesoptional

File patterns to process (glob) Optional for write_file handler which uses path/content instead

#path
string|nulloptional

Target path for write_file handler Supports variable interpolation (${paths.}, ${vars.}, ${ports.*})

#content
string|nulloptional

Inline content for write_file, sql, or shell handlers.

For sql and shell, inline content is used when source_config is omitted and files is empty.

Supports variable interpolation (${paths.}, ${vars.}, ${ports.*})

#then
array<HookAction>optional

Actions to run for every file matched by a for_each_match hook.

#skip_if_matches
array<HookMatchSkip>optional

Sources whose relative matches should shadow primary for_each_match files.

When a fetched primary file has the same relative path as any file from a skip_if_matches source, the primary file is skipped. This keeps overlay semantics generic: block YAML can model mounted files shadowing packaged files without teaching Stackie about a particular product or file type.

#skip_if_path_exists
array<string>optional

Interpolated paths that skip the whole hook when any one already exists.

This models source-image entrypoint guards such as "run init files only before a data directory is initialized" without making the hook executor aware of a specific product, file format, or service.

#skip_if_path_missing
array<string>optional

Interpolated paths that skip the whole hook when any one is missing.

Blocks can pair this with declarative init operations that write marker files when fresh state is created, then run connection-dependent hooks only for that startup.

#binary
string|nulloptional

Binary path for the run handler.

Values support the same interpolation as other hook fields, including ${install.path}, ${paths.}, ${vars.}, ${env.}, and ${ports.}.

#args
array<string>optional

Command-line arguments for the run handler.

Each argument is interpolated independently before the existing Stackie declarative run operation executes the process.

#working_dir
string|nulloptional

Optional working directory for the run handler.

#vars
map<string, string>optional

Variable overrides applied while this hook runs.

Overrides are merged into the handler context before source paths, inline content, and handler connection settings are interpolated. Nested then actions can add their own overrides on top.

#require_matches
booleanoptional

Whether for_each_match should fail when no files match.

#order
integeroptional

Execution order (lower = earlier)

#continue_on_error
booleanoptional

Continue executing hooks if this one fails

#sql_ignore_error_codes
array<string>optional

PostgreSQL SQLSTATE codes that should be treated as successful no-ops.

This keeps idempotent SQL hooks precise: the hook can tolerate one known database state, such as a duplicate catalog object, while still failing on all other SQL errors.

#sql_skip_if
string|nulloptional

SQL query that skips this SQL hook when it returns at least one row.

The query uses the same connection string and interpolation context as the hook's SQL content. This lets block definitions avoid expected database errors, such as duplicate catalog objects, instead of executing failing SQL and relying on ignored SQLSTATE codes that still pollute service logs.

#timeout_secs
integer|nulloptional

Timeout for this hook in seconds

#run_once
booleanoptional

Run this hook only once per block version per project.

When true, the hook is skipped on subsequent stackie up invocations if a matching (block_name, block_version, project_name) record exists in block_init_runs. If no database pool is available, or the block version is "latest", the hook always runs.

Only meaningful on after_healthy hooks. Ignored on all other hook points.

#HookFiles

File patterns configuration for hooks, supporting single or multiple file globs.

#HookMatchSkip

Match source whose relative file paths should shadow a hook's primary matches.

This is used by for_each_match hooks that model layered filesystems. For example, Docker bind mounts can overlay files from an image directory; Stackie can then fetch both sources while ensuring only the top-most file for a given relative path is processed.

#source_config
SourceConfigrequired

Source to inspect for shadowing matches.

#files
array<string>optional

File patterns to match in the shadowing source.

#InitSection

Used in full exampleDeclarative init section

Initialization steps. Prefer declarative operation objects; legacy platform command entries remain readable during migration.

#MockerConfig

Maps Docker image names to this block, enabling Docker CLI and docker-compose to work transparently with Stackie's Docker Engine API.

mocker:
  version_regex: "^(\\d+(?:\\.\\d+)*)"
  images:
    - postgres
    - name: library/postgres
    version_regex: "^(\\d+)"
    - name: docker.io/library/postgres
#built_in
booleanoptional

Whether this Docker-compatible image is supplied by Stackie's bundled runtime instead of an installed package source.

Built-in images are still declared by block YAML, so mocker continues to resolve Docker image names through the same catalog path as installable packages. Pull requests for built-in blocks report an already-present image and do not mutate package state.

#built_in_version
string|nulloptional

Docker-facing version reported for a built-in image.

Use this when a compatibility block intentionally emulates a known image tag while the Stackie block name remains honest about the implementation.

#version_regex
string|nulloptional

Default regex for extracting version from Docker image tags. Applied to all images unless overridden. Example: ^(\d+(?:\.\d+)*) extracts "15.2" from "postgres:15.2-alpine"

#images
array<MockerImage>optional

Docker image name aliases that map to this block. Supports both simple strings and extended objects.

#host_aliases
array<string>optional

Additional Docker/Compose hostnames that should resolve to this block.

Some Docker-compatible gateway configs route to stable upstream hostnames that are not the Compose service name or generated container name. Stackie exports these aliases into the Compose endpoint catalog so thin adapters such as Donkey can route through the same generic service resolver.

#code_mount
string|nulloptional

Container path where user source code is mounted.

When non-None, this block is treated as a user-code runtime block. The user-code detector uses this path to validate bind-mount targets (Pattern A) and to set the default working directory for translated blocks.

Example: /app for Node.js, /workspace for Go.

#default_command
array|nulloptional

Default entrypoint command for runtime blocks.

When a container or pod is started with this block's image but no explicit command, this default is used by the user-code detector translation.

Example: ["node", "index.js"] for Node.js, ["python", "main.py"] for Python.

#run_whitelist
array|nulloptional

Package manager commands that mocker is allowed to execute during Dockerfile RUN interception (Tier-1 whitelist).

Only argv[0] is matched. Commands not in this list produce a Tier-2 diagnostic pointing users at tools:.

Example: ["npm", "yarn", "pnpm", "npx"] for Node.js.

#MockerImage

An entry in mocker.images. Use a plain string for the common case; use the extended object form to override version_regex for a specific image.

# Simple — image name only images: - postgres - redis

# Extended — override version_regex for this image images: - name: postgres version_regex: "^(\\d+)" - name: library/postgres version_regex: "^(\\d+\\.\\d+)" - name: supabase/studio source_version: "v1.26.05" 

#PlatformOrString

An environment variable value that can be either a plain string or platform-conditional.

Mirrors the pattern used by sources.web.url for per-platform URL specification, but applied to environment variable values in Block::tool_env.

tool_env:
  GOROOT: "${install_path}"
tool_env:
  JAVA_HOME:
    linux: "${install_path}"
    macos: "${install_path}/Contents/Home"
    windows: "${install_path}"
  • PlatformUrl for the same pattern applied to download URLs - Block::tool_env for the field on the Block struct

#PlatformSupport

Platform support flags for blocks

Indicates which operating systems an block can run on.

#macos
booleanoptional
#windows
booleanoptional
#linux
booleanoptional

#PlatformUrl

URL for a specific platform - can be a single string or arch-specific

#PlatformUrls

Platform-specific URL mapping

Maps operating systems to download URLs. Each platform can have either a simple URL or architecture-specific URLs.

#linux
PlatformUrl|nulloptional

URL(s) for Linux

#macos
PlatformUrl|nulloptional

URL(s) for macOS

#windows
PlatformUrl|nulloptional

URL(s) for Windows

#PortConfig

Used in full exampleServed database port

Port configuration with number and type

#port
integerrequired

Port number

#type
PortType|nulloptional

Port type classification (optional, defaults to None for backward compatibility)

#expose
booleanoptional

Whether this served port should be shown as a stack-level external link.

#label
string|nulloptional

Optional display label for an exposed external link.

#protocol
string|nulloptional

URL scheme for exposed external links.

#PortType

Port type classification

ValueDescription
"web"

Web service port (HTTP, HTTPS, WebSocket, etc.)

"db"

Database port

"admin"

Administration/management port

"api"

API endpoint port

"metrics"

Metrics/monitoring port (Prometheus, StatsD, etc.)

"grpc"

gRPC service port

"messaging"

Message queue/broker port (AMQP, MQTT, STOMP, etc.)

"misc"

Miscellaneous port

#SandboxPermission

Used in full exampleSandbox permission

Sandbox permission for block-level access control

Defines filesystem paths that require non-standard sandbox permissions beyond the default sandbox policy. Use sparingly - only for exceptional cases where an block needs specific system access.

#path
stringrequired

Absolute filesystem path

#mode
stringrequired

Permission mode: combination of r/w/x (e.g., "rwx", "rx", "r")

#Sha256ArchHashes

Architecture-level SHA256 hashes

#amd64
string|nulloptional

Hash for AMD64/x86_64 architecture

#arm64
string|nulloptional

Hash for ARM64/aarch64 architecture

#Sha256Hash

SHA256 hash specification for archive verification

Supports two levels of granularity: 1. Simple: Single hash for all platforms (when same archive for all) 2. Platform/Arch: Different hashes per platform and architecture

#Sha256PlatformHashes

Platform-level SHA256 hashes

#macos
Sha256ArchHashes|nulloptional

Hashes for macOS (by architecture)

#linux
Sha256ArchHashes|nulloptional

Hashes for Linux (by architecture)

#windows
Sha256ArchHashes|nulloptional

Hashes for Windows (by architecture)

#SourceConfig

Content source configuration for hooks

Defines where to fetch hook content from. Each variant maps to a ContentSource implementation in the handlers module.

use stackie::hooks::SourceConfig;

// Git source for upstream scripts let git = SourceConfig::Git { url: "https://github.com/supabase/postgres".to_string(), reference: Some("v15.1.0.117".to_string()), sparse_paths: None, };

// Local source for custom scripts let local = SourceConfig::Local { path: "/opt/stackie/scripts".to_string(), };

Accepted shapes

Fetch content from a Git repository

Uses the GitSource implementation which:

  • Clones/fetches the repository - Checks out the specified reference - Reads files from the working tree

required: type, url

Fetch content from a web URL

Uses the WebContentSource which:

  • Downloads files via HTTP/HTTPS - Supports basic authentication - Caches downloaded content

required: type, url

Read content from local filesystem

Uses the LocalContentSource which:

  • Reads files from the specified directory - Supports glob patterns - Fast and reliable for local scripts

required: path, type

No external source - content is provided inline

Used by handlers like write_file that don't fetch content from an external source but instead receive content directly in the hook definition.

required: type

#SourceDefinition

Source definition for a package manager within a block.

This describes how a block is acquired from one provider. The package name, URL template, checksum, archive shape, and platform mappings are shared by every supported block version. Self::version is optional and overrides the block's versions.latest value only when the provider needs a distinct channel or constraint.

#name
stringrequired

Package name in the source system Example: "postgresql" for brew, "@nestjs/core" for npm

#version
stringoptional

Optional provider-specific version or version constraint.

An empty value inherits the canonical version mapped by the block's latest version alias. Set this only when the provider requires a different selector, such as a package-manager channel or constraint. Examples: "15", "^2.1.0", "latest".

#version_template
string|nulloptional

Optional provider spelling applied to the canonical block version.

The template must contain exactly one {version} placeholder and may add provider-required punctuation around it. For example, a Go module whose tags are prefixed with v uses "v{version}", while its web URL can continue to interpolate the unprefixed canonical version. This is not a URL template and cannot add path separators.

#cache
booleanoptional

Whether this source should be cached on the Cache CDN

Defaults to true. When enabled, stackie will check the Cache CDN first before falling back to the direct source URL. This provides faster, more reliable downloads through a nearby CDN.

Set to false to opt out of CDN caching for sources that should always be fetched directly from upstream (e.g., rapidly changing packages).

Package manager sources (brew, scoop, pip, etc.) ignore this field as they are inherently non-cacheable.

#url
WebUrl|nulloptional

Download URL for web sources (optional, used by web source type)

Supports three formats:

  • Simple string: Same URL for all platforms
  • Platform map: Different URLs per OS - Platform+Arch map: Different URLs per OS and architecture
#tap
string|nulloptional

Homebrew tap (optional, used by brew source type) Example: "mongodb/brew", "hashicorp/tap"

#ecosystem
Ecosystem|nulloptional

Ecosystem type for supercache sources

Required when using supercache source type to specify which ecosystem the package belongs to (go, node, python, java, etc.)

#platform_specific
boolean|nulloptional

Override whether this package is platform-specific

When set, overrides the ecosystem's default platform-specificity. Use this for Node packages with native dependencies that require platform-specific builds.

#source_url
string|nulloptional

Source URL for fallback compilation (optional)

For Go packages: The Go module path used for go install when falling back from cached binaries to source compilation. Example: "github.com/supabase/auth", "github.com/traefik/traefik/v3"

For other ecosystems: May be used for source compilation fallback.

#after_install
array|nulloptional

Commands to run after installation completes

These commands run in the installation directory after the source has been downloaded/installed. Useful for:

  • Running npm install for Node.js projects - Running npm run build to compile TypeScript - Running pip install -r requirements.txt for Python projects - Any post-installation setup required before the package can be used
#repo
string|nulloptional

GitHub repository for github-releases source (owner/repo format)

Used by the github-releases source type to construct download URLs. Format: "owner/repo" (e.g., "PostgREST/postgrest")

#archive_pattern
string|nulloptional

Archive filename pattern for github-releases source

Supports placeholders:

  • {version} - version tag (e.g., "v12.2.8")
  • {platform} - platform name (e.g., "linux", "macos", "windows")
  • {arch} - archive architecture name (typically "amd64" or "arm64")
#archive_shape

Archive layout for github-releases source.

universal means the archive pattern is the same across platforms. platform_arch means the archive pattern contains platform and/or architecture placeholders and requires matching platform hash metadata.

#platform_mappings
object|nulloptional

Platform placeholder mappings for github-releases archive filenames.

Keys are Stackie platform identifiers (macos, linux, windows); values are the strings used by the release asset naming convention. Omit this field to use the github-releases source defaults.

#arch_mappings
object|nulloptional

Architecture placeholder mappings for github-releases archive filenames.

Keys are Rust-style architecture identifiers (x86_64, aarch64) plus any block-facing aliases (amd64, arm64) that the installer may use; values are the strings used in the release asset names. Omit this field to use the github-releases source defaults.

#sha256
Sha256Hash|nulloptional

SHA256 hash verification for downloaded archives

Supports two formats:

  • Simple string: Single hash for all platforms (when URL is same for all) - Platform/arch map: Different hashes for different platform/arch combinations

Required for github-releases source. Optional but recommended for web source.

#ToolLicenseInfo

License metadata for tool blocks requiring acceptance prompts.

Stores the minimal information needed to display a license acceptance prompt before a tool is installed. Use tool_license on tool: true blocks to require explicit user acceptance before installation.

tool_license:
  name: "GPL v2 with Classpath Exception"
  url: "https://www.gnu.org/licenses/old-licenses/gpl-2.0.html"
  publisher: "Adoptium"
  • BlockVersionEntry for version listing - Block::tool_license for the field on the Block struct
#name
stringrequired

Human-readable license name (e.g., "MIT License", "GPL v2 with CE")

#url
stringrequired

URL to the full license text

#publisher
stringrequired

Publisher or organisation that holds the license (e.g., "Adoptium", "Microsoft")

#ToolRequirement

One runtime tool requirement in the exact custom-Serde form accepted by block YAML: either a non-empty tool name or a one-entry tool-to-version map.

Accepted shapes

#WebUrl

URL specification for web sources

Supports three levels of granularity: 1. Simple: Single URL for all platforms/architectures (e.g., Java JARs) 2. Platform: Different URLs per platform (linux, macos, windows) 3. Full: Different URLs per platform AND architecture