Do-nothing scripting

Dan Slimmon’s 2019 technique for killing slogs — “focus-intensive yet thought-free” procedures (provisioning accounts, infra changes, 20-step checklists). The perception that blocks automating them: it feels all-or-nothing — a script for one step just adds to the pile of single-purpose scripts, and the multi-step doc remains.

The move: write a script that does nothing. It encodes the procedure, prints each step’s instructions, and waits for Enter — the human still performs every action. The script’s value isn’t saved effort:

  1. You can’t lose your place — no skipped steps, sustained focus through the slog
  2. Each step is a function — any step’s text can later be replaced by code that actually does it, one at a time
  3. A step library accretes — future procedures compose from proven steps

“A do-nothing script doesn’t save your team any manual effort. It lowers the activation energy for automating tasks, which allows the team to eliminate toil over time.” The deep point: encode the procedure as code before you can automate any of it — the runnable checklist is the scaffold each step gets automated into, in whatever order reality demands, without a rewrite. It’s strangler-fig (Fearless refactoring) applied to runbooks: the human is the old system, replaced piece by piece.

The companion pattern: terminal frontend architecture (lifehacker.dev)

The natural next step after the do-nothing script starts growing real logic — split the asking from the doing:

  • Core logic: takes arguments, asks nothing, returns an exit code — the part that touches production
  • Frontend (e.g. a gum TUI menu): asks the human, validates answers, calls the core with those answers as arguments

“The core never knows whether a human or a cron job filled in its arguments” — the same deploy_app prod v1.4.2 runs behind a friendly menu and unattended in CI. Mix the two and you lose both. Validation lives in the frontend, deliberate-yes guards production, and the do-nothing script’s interactive layer can then become the frontend without touching the core. The pair is the full arc: runnable checklist → stepwise automation → arg-driven core + disposable frontends.

Kinship and caveats

  • Kubernetes Operators is the endpoint of this ladder when the steps are state reconciliation — the do-nothing script for “restore the cluster” eventually is an operator. Rewriting Ansible roles from K8s operators borrows the direction.
  • Musk engineering process step 5 (automate last) is the same sequencing discipline: the do-nothing script is automation that deliberately doesn’t automate.
  • HN discussion (two threads, 2021 + 2025 — the article resurfaces because the problem never dies): recurring critiques worth keeping — checklists drift from reality unless run (Fearless refactoring’s social effect in miniature), and pstack-style agent verification is the 2026 answer to the same toil (an agent that runs the checklist and proves the steps — pstack).
  • The raw_input waits also make steps observable — each Enter is a checkpoint record; add timestamps and you have a free execution log (the full-featured/KISS split from Operating principles fits here).

Related: Fearless refactoring (strangler fig kin) · Kubernetes Operators (the ladder’s endpoint) · pstack (agents as the checklist runner) · Golden repo

The destination engine: dagu (runbooks → production workflows)

dagu (OSS) (4.3k★, Go; dagu.sh; via @bearstech — “une alternative open source à Airflow qui mise sur une approche déclarative en YAML”) is what the do-nothing arc lands in when the scripts graduate: declarative YAML over your existing scripts, SSH commands, containers, and K8s Jobs — one binary, built-in Web UI, no external database or message broker, runs where the credentials live (on-prem/air-gapped/edge). Scheduling, retries, human tasks (the do-nothing step, productized), run history. Positioned precisely for “teams whose main work isn’t orchestration” — Airflow’s weight without writing Python DAGs; cron’s simplicity with state. The evolutionary line: runnable checklist → arg-driven core → YAML DAG wrapping those cores unattended.