Lesson 5.3

References & Further Reading

CLI design, Go tooling, and compilation pipeline resources.

links 5 min read

CLI design principles.

Command Line Interface Guidelines

clig.dev

The best single resource on CLI design. Covers conventions for flags, output, errors, exit codes, colors, and help text. Written by practitioners, not academics. If you read one thing on this list, read this.

clig.dev

12 Factor CLI Apps

by Jeff Dickey

Adapts the 12-factor app methodology to CLI tools. Covers configuration, error handling, help text, and distribution. The "prefer flags over env vars, prefer env vars over config files" hierarchy is useful for any CLI.

medium.com/@jdxcode/12-factor-cli-apps

Monk's CLI follows the Unix tradition: do one thing, use exit codes, write errors to stderr, produce machine-parseable output. The resources above codify these conventions.

Go standard library for CLIs.

Go flag package

The standard library's flag parsing. No framework needed for simple CLIs. Handles -o, -v, boolean flags, string flags, and usage text. Monk uses this for the -o output flag.

pkg.go.dev/flag

Go embed package

Lets you bake files into the compiled Go binary at build time. Monk uses this to embed the C runtime (runtime.h and runtime.c) so users get a single binary with no external dependencies.

pkg.go.dev/embed

Go os/exec package

Used to invoke the system C compiler. Provides process creation, stdin/stdout/stderr piping, and exit code retrieval. The interface between the Go compiler and the C compiler is just a subprocess call.

pkg.go.dev/os/exec

Compilation pipeline design.

GCC Compilation Stages

GCC's pipeline (preprocessing, compilation, assembly, linking) is the reference model for how compilation works. Understanding GCC's stages helps explain why Monk's two-phase approach (Monk-to-C, then C-to-binary) is natural -- it's just inserting a step before GCC's own pipeline.

gcc.gnu.org/onlinedocs/gcc/Overall-Options.html

Clang Driver Architecture

Clang's driver is the CLI that orchestrates compilation. Its architecture documentation shows how a production compiler handles the same problems Monk solves: finding the right tools, managing temp files, chaining pipeline stages. A more complex version of the same pattern.

clang.llvm.org/docs/DriverInternals.html

Inspiration for the build/run split.

Rust's Cargo

Cargo's cargo build and cargo run established the pattern that Monk follows. Build produces an artifact. Run produces an artifact, executes it, and cleans up. The separation is about intent: are you producing something to ship, or just testing an idea?

doc.rust-lang.org/cargo

Go's go build / go run

Go itself uses the same split. go build produces a binary. go run compiles to a temp binary, runs it, and discards it. Monk's implementation mirrors this approach -- unsurprising, since Monk's compiler is written in Go.

pkg.go.dev/cmd/go

Build systems and history.

Make -- the original build orchestrator

Before compilers had built-in build commands, Make handled the pipeline: which files to compile, in what order, with what flags. Understanding Make's dependency graph model explains why modern compilers internalize this logic. Monk's CLI does what a Makefile would have done -- but the user never writes one.

gnu.org/software/make/manual

"Recursive Make Considered Harmful"

by Peter Miller

A classic paper on build system design. While Monk is too small to have build system problems, the paper explains why languages eventually absorb their build tools. Monk starts where Go and Rust ended up: the compiler IS the build system.

Suggested reading order.

1

Command Line Interface Guidelines -- the conventions Monk follows. Read this first to understand why the CLI is shaped the way it is.

2

Go flag and embed packages -- the two standard library packages that do the heavy lifting in Monk's CLI.

3

GCC compilation stages -- for understanding the pipeline that Monk's generated C enters after the Monk compiler is done.

4

Cargo and go build -- see how mature tools handle the same build/run split.

5

Clang driver internals -- only if you're curious about how a production compiler CLI handles hundreds of flags and targets. Not needed for Monk's scale.