It’s occasionally useful to introduce pause points into procedures. The idea is that, when a human operator is about to do something scary, we want them to stop and think for a second and not just do things by rote. Enter challenge-prompt, a small program and Rust library which challenges the user to type something.

You can install it from

$ cargo install challenge-prompt

Without any arguments, the program issues an arithmetic challenge:

$ challenge-prompt
Solve: (5 + 15) mod 5 = ?

It can also make the user type in a phrase exactly:

$ challenge-prompt -p "I am probably making a mistake"
Enter the following exactly to continue: I am probably making a mistake

It can also output a vanilla yes/no prompt, but my experience is that it’s very easy to internalise typing ‘y’ after commands:

$ challenge-prompt -y
Continue? [y]

All of this is also exposed as a Rust library.

An aside on Rust binary sizes

One issue I had writing challenge-prompt is that Rust binaries tend to be big. This is generally not a problem, but there’s something aesthetically displeasing about a program as simple as challenge-prompt being multiple megabytes in size.

I found that the following settings struck a good balance between size and additional complexity. They are ordered in decreasing order of size improvement.

  1. Don’t have any dependencies outside of the dev profile.

  2. Enable Link Time Optimisations for the release profile in Cargo.toml:

    lto = true
  3. Use the system allocator in

    use std::alloc::System;
    static GLOBAL: System = System;
  4. Abort on panic in Cargo.toml:

    panic = "abort"

These all reduced challenge-prompt’s size from 4MB to just shy of 1MB.

Stripping the executable would shrink it to about 240KB, but that’s hard if not impossible to setup in cargo automatically. Dropping the dependency on stdlib would have likely further reduced the size, but that would make the code too fiddly for my tastes.