scafctl#

Define, discover, and deliver configuration as code using CEL-powered solutions.

scafctl is a CLI tool that lets you declaratively gather data from any source — APIs, files, environment variables, Git, and more — transform it with CEL expressions, and execute side-effect workflows, all defined in a single Solution file.

Go Report Card License Release


Quick Install#

brew install oakwood-commons/tap/scafctl

Or download a binary from GitHub Releases .


30-Second Example#

Create a file hello.yaml:

apiVersion: scafctl.io/v1
kind: Solution
metadata:
  name: hello
spec:
  resolvers:
    greeting:
      type: string
      resolve:
        with:
          - provider: cel
            inputs:
              expression: "'Hello, ' + 'world!'"

Run it:

scafctl run solution -f hello.yaml -o yaml
# greeting: Hello, world!

Core Concepts#

ConceptDescription
SolutionA YAML file declaring what data to gather and what work to do. Versionable, composable, and shareable via OCI registries.
ResolverA named unit that gathers or computes a value using one or more providers. Resolvers can depend on each other and execute in parallel.
ActionA side-effect operation (run a command, call an API, write a file) organized into a dependency graph with parallelism, retries, conditions, and forEach loops.
ProviderA pluggable backend that does the actual work. scafctl ships with 18 built-in providers and supports external plugins.

Built-in Providers#

scafctl ships with 18 providers out of the box:

cel · debug · directory · env · exec · file · git · github · go-template · hcl · http · identity · metadata · parameter · secret · sleep · static · validation

# List all providers
scafctl get provider

# Inspect a specific provider's schema and examples
scafctl explain provider http

Key Features#

  • CEL Integration — Use Common Expression Language for dynamic evaluation, filtering, and transformation
  • Dependency Graph — Resolvers and actions model their dependencies; scafctl executes in parallel where possible
  • Catalog — Publish, version, and share reusable solutions via OCI-compatible registries
  • Secrets — Encrypted secrets management backed by the OS keyring
  • Plugins — Extend scafctl with custom providers via a gRPC plugin system
  • Snapshots — Capture and diff resolver output over time
  • Dry Run — Preview what actions would do without executing them
  • Linting — Validate solution files before execution
  • Auth — Microsoft Entra ID (Azure AD) device code and service principal flows

Documentation#

Get Started#

Go Deeper#


Example: CI/CD Pipeline#

apiVersion: scafctl.io/v1
kind: Solution
metadata:
  name: pipeline
spec:
  resolvers:
    servers:
      type: array
      resolve:
        with:
          - provider: static
            inputs:
              value: ["prod-1", "prod-2"]

  workflow:
    actions:
      build:
        provider: exec
        inputs:
          command: "go build ./..."

      test:
        provider: exec
        dependsOn: [build]
        inputs:
          command: "go test ./..."

      deploy:
        provider: exec
        dependsOn: [test]
        forEach:
          in:
            expr: "_.servers"
          concurrency: 2
        inputs:
          command:
            expr: "'deploy.sh ' + __item"

    finally:
      notify:
        provider: http
        inputs:
          url: "https://hooks.slack.com/..."
          method: POST