What Is pkfire?
pkfire is a typed task runner built by mizchi that replaces stringly task files with Pkl-defined schemas, and pkf is the CLI that executes them for developers, monorepo maintainers, and CI engineers. It is one of the best Task Runners tools for monorepo maintainers, CI engineers, and developers replacing shell-script task files. The project ships a DAG-based executor, content-addressed caching, and cross-platform GitHub Actions support for linux/darwin × amd64/arm64, so repeated work is skipped instead of recomputed.
The core idea is simple: task definitions are typed, dependencies are real references, and the runner only executes tasks whose action key changed. That makes pkfire a good fit when you need deterministic builds, cache reuse across local machines and CI, and fewer Friday-night failures caused by misspelled task names.
Quick Overview
| Attribute | Details |
|---|---|
| Type | Task Runners |
| Best For | Monorepo task orchestration, CI pipelines, and typed build/test workflows |
| Language/Stack | Pkl, Go, Bash, GitHub Actions, Nix |
| License | N/A |
| GitHub Stars | N/A as of Feb 2026 |
| Pricing | Open-Source |
| Last Release | v0.10.0 — N/A |
Who Should Use pkfire?
- Monorepo teams that have repeated
build,test, andlintrecipes across dozens of packages and want a typed schema instead of copy-pasted shell. - CI engineers who need cache hits to survive across local dev, GitHub Actions, and self-hosted runners without rebuilding the same artifacts.
- Platform teams managing platform matrices such as
linux-amd64,linux-arm64,darwin-amd64, anddarwin-arm64where one template should generate many tasks. - Developers standardizing task definitions who want validation at Pkl evaluation time instead of discovering broken dependency names during execution.
Not ideal for:
- Tiny repositories with three one-line scripts where
makeorjustis already enough. - Teams unwilling to adopt Pkl as a config language, because pkfire’s main value comes from typed schema and evaluation-time checks.
- Pure ad-hoc shell automation where the command itself is the only artifact and there is no DAG, cache, or task reuse problem.
Key Features of pkfire
- Typed Pkl task schemas — Tasks are defined as Pkl objects, not opaque strings, so the schema can be validated before the runner starts. That catches broken names and invalid structure earlier than a shell-only task file.
- DAG-based execution — pkfire builds a dependency graph from
depsreferences and runs tasks in graph order. Independent nodes can be skipped or reused when their action key and inputs have not changed. - Content-addressed cache — Cached outputs are stored under
~/.cache/pkfire, keyed on inputs, command, and environment. This makes repeated local runs fast and keeps the cache model predictable for CI. - Remote cache support — An HTTP remote cache lets teammates and CI share hits instead of rebuilding the same targets on every runner. That is the right fit for teams that already use shared build caches and want parity between laptop and pipeline.
- Template reuse with
amends— A project canamendsthe schema frompackage://pkg.pkl-lang.org/..., which means a starterTaskfile.pklcan live in the package registry rather than a copied repo clone. That reduces boilerplate across many services. - Per-module validation — Pkl’s
pkl testand ordinary functions make task files testable as configuration, not just executable text. Misspellings become evaluation errors instead of runtime surprises. - Flexible shell execution — Tasks support configurable
shellandshellFlags, sobash -c, strict mode, or evennode -estyle execution can be expressed cleanly. This helps teams keep task logic explicit instead of hiding assumptions in wrapper scripts.
pkfire vs Alternatives
| Tool | Best For | Key Differentiator | Pricing |
|---|---|---|---|
| pkfire | Typed task runners for monorepos and CI | Pkl-typed schema, DAG execution, and cache-aware task reuse | Open-Source |
| make | Universal build automation | Ubiquity and minimal syntax, but string-based dependencies | Free |
| just | Lightweight command recipes | Simple justfile ergonomics without typed config | Open-Source |
| go-task / Taskfile.yml | YAML-based task orchestration | Familiar YAML task files and cross-platform scripting | Open-Source |
Pick make when you need something every Unix box already understands and the workflow is small enough that stringly dependencies will not hurt. Pick just when you want a cleaner command runner than make but still want tiny, readable recipes.
Pick go-task when your team prefers YAML and a conventional Taskfile.yml layout. Pick pkfire when task reuse, type safety, and cache keys matter more than staying inside plain shell text.
If you are wiring broader DevOps glue around shell commands, djevops is the closer fit. If you are comparing automation tools more generally, browse all DevOps Automation tools to see the surrounding ecosystem.
How pkfire Works
pkfire separates the schema layer from the execution layer. The schema lives in Pkl, where each task is a typed Task object with name, cmd, inputs, outputs, and deps, and the CLI resolves those references into a DAG before execution. That design keeps the configuration evaluable and lets Pkl catch invalid references before the runner touches the shell.
The execution layer hashes the task’s action key from its command, declared inputs, and environment, then stores outputs in a content-addressed cache under ~/.cache/pkfire. When a task’s key matches a previous run, pkfire restores the output instead of rerunning the command, which is the main reason it performs well in monorepos with many near-identical targets.
amends "package://pkg.pkl-lang.org/github.com/mizchi/pkfire/[email protected]#/Taskfile.pkl"
local build = new Task {
name = "build"
cmd = "go build -o bin/app ./cmd/app"
inputs { "**/*.go"; "go.mod"; "go.sum" }
outputs { "bin/app" }
}
local test = new Task {
name = "test"
cmd = "go test ./..."
inputs { "**/*.go" }
deps { build }
}
tasks { build; test }
That example defines a build task, a test task, and a direct typed dependency between them. pkfire can then skip work if the relevant inputs and command fingerprint did not change, which is exactly what you want for repeatable CI and fast local iteration.
Pros and Cons of pkfire
Pros:
- Typed dependencies remove the fragile string references that break only after a task is invoked.
- Incremental caching restores outputs from a content-addressed store instead of rerunning every shell command.
- Remote cache sharing reduces duplicate work across developers and CI runners.
- Pkl-based composition makes large task sets easier to template, test, and refactor.
- Cross-platform packaging via Go, GitHub Actions, and Nix makes it practical in mixed Linux/macOS teams.
- Clear task discovery walks up directories to find the nearest
Taskfile.pkl, which helps nested service repos.
Cons:
- Pkl is a new dependency for teams that only want plain shell files.
- The mental model is heavier than
justbecause you need to think about inputs, outputs, dependencies, and cache keys. - Cache correctness depends on accurate declarations; if inputs are under-declared, stale reuse is possible.
- Ecosystem familiarity is lower than
makeorgo-task, so onboarding may take longer. - Best results require structured repositories; one-off scripts do not benefit much from DAG planning or remote cache plumbing.
Getting Started with pkfire
go install github.com/mizchi/pkfire/cmd/pkf@latest
pkl --version
pkf init
pkf run hello
That flow installs the CLI, verifies that the Pkl CLI is available, generates a starter Taskfile.pkl, and runs the first task. After that, you usually edit the generated schema, add your real tasks, and run pkf run <task> from the repository root or any nested directory that can discover the nearest task file.
For CI, the easiest path is the GitHub Action shipped in the repo root. It installs pkf and the matching Pkl binary, then exposes them on PATH, so later steps can call pkf run ci without bootstrapping Go or Pkl inside the workflow.
Verdict
pkfire is the strongest option for typed task orchestration in monorepos when you care about cache reuse and early schema validation. Its biggest strength is the combination of Pkl typing and content-addressed incremental execution. The main caveat is that you must accept Pkl and maintain honest input declarations. If you want deterministic task files instead of shell strings, choose pkfire.


