I recently released a small open-source terminal command called begin, for running logic-less project templates. The goal of the project is to make it easy for teams and individuals to reduce the amount of repetitive work in starting a new project, and to help them ensure new projects start off at quality.

Begin Terminal Command

Motivation

The motivation for this command stems from my experience in working on a software team that had a relatively small number of engineers that were responsible for maintaining a large quantity (hundreds) of small software projects.

A high ratio of projects to engineers had some interesting consequences. It created opportunity where different software projects could adopt vastly different practises. Some of these differences were harmless (coding style), but others certainly affected the software quality (testing strategy for instance). Decisions about which coding style, testing framework, build system, etc were often deferred to the engineers writing the software, rather than having some central authority to make these decisions and enforce them. It is only natural and healthy for opinion and level of experience to vary greatly across an engineering team, but in this environment, this naturally lead to some inconsistency.

This inconsistency made it difficult to roll out wide-spread improvements across all software projects. Engineers would only ever be exposed to a small subset of these projects, and so this typically required the entire engineering team to coordinate and share this work, and it could sometimes be difficult to balance this maintenance against the day-to-day demands of production. In striving to do better, it was important to ensure new projects adopted best practises from the moment they were started.

Software Scaffolding

This is where software scaffolding can help. A scaffold is a small interactive program that guides the user through the creation of a new project. The concept was made popular by Ruby on Rails which provides a scaffold command to automatically generate a model, view, and controller for an entity in your web app - in doing so, it creates the boilerplate code, sets up unit test modules, and enforces a consistent project structure by convention.

My idea was to adopt something similar for new software projects. The idea was that a developer could run begin new maya-plugin for example, and it would ask the developer a few questions about their new project, and then construct for them the source code for a boilerplate Maya plugin, along with the code necessary to spin up Maya in batch mode for unit tests, and build scripts that were compatible with our internal build system.

I also imagined this having to scale up to support several project variants, for example:

  • begin new maya-plugin
  • begin new houdini-plugin
  • begin new nuke-plugin
  • begin new clarisse-plugin
  • begin new standalone-app

If that were to happen, then we would need to ensure the creation and maintenance of these scaffolds was cheap. Specifically, cheaper than the cost of having to maintain the source code for an equivalent scaffolding script.

Template-Driven Scaffolding

One alternative to expressing a scaffold in terms of source code is to express it in terms of a template.

This is the approach that forms the basis of begin. In begin a template is simply a collection of files and directories. These can be placed in a Git repository, such that a template can be shared across teams, and can evolve over time. begin has commands for installing, removing, and updating templates from Git:

  • Install a template from Git with the begin install command
  • Update a Git-based template with the begin update command
  • Uninstall a template with the begin uninstall command

File names, directory names, and file content are permitted to contain Mustache tags. When creating your template, you can tell begin about expected tags, and begin will then prompt the user for their values when the template is evaluated. The benefits of using Mustache is that whilst it is logic-less, it supports many useful templating concepts such as false values, and arrays of values. begin can take advantage of this - for instance, when you tell begin that a template tag expects an array of values, begin will prompt the user for multiple values in the terminal.

Simple Example

Suppose we have a template consisting of two files:

  • .begin.yml
  • Example.txt

We have a template configuration (.begin.yml) which tells begin that we are expecting one tag called name. As part of the configuration, we also give this tag a human-readable label that can be printed to the terminal:

tags:
    name:
        label: Your Name

We also have a content file (Example.txt) which contains a Mustache tag:

Hello {{name}}

Upon evaluating the template, begin checks the template configuration to see which tags are expected, and prompts the user for their values. This is then passed to Mustache which substitutes these values into the resultant files. The template is evaluated by using the begin new command:

$ begin new example-template
Your Name: World
Running Template 'example-template'...
Template 'example-template' successfully run

The directory will now have a file called Example.txt containing the string Hello World.

File and Directory Names

Whilst the above example is very simple, it should be possible to imagine this scaling to more complicated use cases, in which your template contains source files, unit tests, build scripts, and uses various Mustache tags to customise this content when the template is evaluated.

Another powerful feature of begin is that file and directory names are also permitted to contain Mustache tags.

Suppose that in the previous example, your template contained another file called {{name}}.txt. This would be evaluated to World.txt in the destination directory.

Conclusion

begin provides a simple way to construct and evaluate template-based scaffolds, and share them with others. If you are interested, please try it!