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.
Full expressions when you need them. Parentheses switch to expression syntax with operators, calls, and whitespace insignificance:
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 protocols — HTTP, JSON, XML, YAML, SQLite, regex, base64, hashing, zip
Tooling — LSP server, REPL
Get Started
New to Do? Start with the Language Guide.
Learn by example? Check out Examples showing real-world use cases.