Skip to content

Do Language

A scripting language for CI/CD, DevOps, and automation that melds declarative elegance with Unix elbow grease:

  • Flexibly define structured data and operate on it with lightweight, indentation-oriented syntax.
  • Run external CLI programs directly.
  • Use built-in modules for common tasks such as HTTP, SQLite, and more.
  • Write ordinary code too: data structures, closures, iterators, classes, exceptions, concurrency.

Experimental Language

Do is still in rapid development. The language syntax, standard library, and API are subject to change. Not recommended for production use.

Why Do?

Simple syntax for shell-script tasks. Bare words are strings, $ introduces variables and expressions.

run gcc -o main main.c -Wall -Werror -lm

Full expressions when you need them. Parentheses switch to expression syntax with operators, calls, and whitespace insignificance:

let total = (price * tax_rate + shipping)

Structured data with YAML-like vertical layout. Build nested data naturally — no separate data format needed:

let config =
  host: localhost
  port: 8080
  features:
    - logging
    - metrics
  limits:
    max_connections: 100
    timeout: 30

Declarative Meets Procedural

Mixed structured data and code in the same syntax and runtime:

# Build a container with podman with progress tracking
import progress container.podman: podman

let PACKAGES =
  - gcc
  - node

progress.with do podman.build
  from: fedora:42
  add:
    target: /etc/sudoers.d/wheel
    chmod: 0o640
    content: |
      %wheel ALL=(ALL) NOPASSWD: ALL

  run: do progress.show
    total: $PACKAGES.len
    message: installing packages
    icon: 📦
    do |i|
      for pkg = PACKAGES
        i.message = "installing $pkg"
        run dnf install -y $pkg
        i.delta()

  tag: my-image

The PACKAGES list, progress.show call, and for loop are ordinary Do code — the run: do block is a closure, not a quoted string passed to a shell.

Unix Tool Integration

External programs become callable functions:

import proc.run:
  - uname
  - git

# Capture output
let kernel = sub do uname -r
let branch = sub do git rev-parse --abbrev-ref HEAD

echo "Building on $kernel, branch $branch"

Container Transparency

Do can run programs and access files inside containers while running on the host:

import shlex
import container.podman: podman
import fs:
  - open

# Read a key from a shell-quoted config file inside a container
def read_key ctr path key
  podman.with $ctr do open $path do |file|
    for line = file
      let k v = line.split = limit: 1
      if (k == key)
        return next(shlex.split v)

echo $ read_key ubuntu:24.04 /etc/os-release PRETTY_NAME

Included Features

Automation — run external programs as functions (proc.run), manage files (fs), build and run containers (podman, docker, toolbx), parse CLI arguments (args), elevate privileges (sudo), read system configuration (systemd, xdg), and show friendly progress indicators.

Data and protocolsHTTP, JSON, XML, YAML, SQLite, regex, base64, hashing, zip

ToolingLSP server, REPL

Get Started

New to Do? Start with the Language Guide.

Learn by example? Check out Examples showing real-world use cases.