Lesson 5.3
References & Further Reading
CLI design, Go tooling, and compilation pipeline resources.
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.dev12 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-appsMonk'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.
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.
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/execCompilation 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.htmlClang 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.htmlInspiration 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?
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.
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.
Command Line Interface Guidelines -- the conventions Monk follows. Read this first to understand why the CLI is shaped the way it is.
Go flag and embed packages -- the two standard library packages that do the heavy lifting in Monk's CLI.
GCC compilation stages -- for understanding the pipeline that Monk's generated C enters after the Monk compiler is done.
Cargo and go build -- see how mature tools handle the same build/run split.
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.